Documentation ¶
Overview ¶
Package kubeaudit provides methods to find and fix security issues in Kubernetes resources.
Modes ¶
Kubeaudit supports three different modes. The mode used depends on the audit method used.
1. Manifest mode: Audit a manifest file
2. Local mode: Audit resources in a local kubeconfig file
3. Cluster mode: Audit resources in a running cluster (kubeaudit must be invoked from a container within the cluster)
In manifest mode, kubeaudit can automatically fix security issues.
Follow the instructions below to use kubeaudit:
First initialize the security auditors ¶
The auditors determine which security issues kubeaudit will look for. Each auditor is responsible for a different security issue. For an explanation of what each auditor checks for, see https://github.com/elliotxx/kubeaudit#auditors.
To initialize all available auditors:
import "github.com/elliotxx/kubeaudit/auditors/all" auditors, err := all.Auditors(config.KubeauditConfig{})
Or, to initialize specific auditors, import each one:
import ( "github.com/elliotxx/kubeaudit/auditors/apparmor" "github.com/elliotxx/kubeaudit/auditors/image" ) auditors := []kubeaudit.Auditable{ apparmor.New(), image.New(image.Config{Image: "myimage:mytag"}), }
Initialize Kubeaudit ¶
Create a new instance of kubeaudit:
kubeAuditor, err := kubeaudit.New(auditors)
Run the audit ¶
To run the audit in manifest mode:
import "os" manifest, err := os.Open("/path/to/manifest.yaml") if err != nil { ... } report, err := kubeAuditor.AuditManifest(manifest)
Or, to run the audit in local mode:
report, err := kubeAuditor.AuditLocal("/path/to/kubeconfig.yml", kubeaudit.AuditOptions{})
Or, to run the audit in cluster mode (pass it a namespace name as a string to only audit resources in that namespace, or an empty string to audit resources in all namespaces):
report, err := auditor.AuditCluster(kubeaudit.AuditOptions{})
Get the results ¶
To print the results in a human readable way:
report.PrintResults()
Results are printed to standard out by default. To print to a string instead:
var buf bytes.Buffer report.PrintResults(kubeaudit.WithWriter(&buf), kubeaudit.WithColor(false)) resultsString := buf.String()
Or, to get the result objects:
results := report.Results()
Autofix ¶
Note that autofixing is only supported in manifest mode.
To print the plan (what will be fixed):
report.PrintPlan(os.Stdout)
To automatically fix the security issues and print the fixed manifest:
err = report.Fix(os.Stdout)
Override Errors ¶
Overrides can be used to ignore specific auditors for specific containers or pods. See the documentation for the specific auditor you wish to override at https://github.com/elliotxx/kubeaudit#auditors.
Custom Auditors ¶
Kubeaudit supports custom auditors. See the Custom Auditor example.
Example ¶
Example shows how to audit and fix a Kubernetes manifest file
package main import ( "fmt" "os" "strings" "github.com/elliotxx/kubeaudit" "github.com/elliotxx/kubeaudit/auditors/all" "github.com/elliotxx/kubeaudit/config" log "github.com/sirupsen/logrus" ) func main() { // A sample Kubernetes manifest file manifest := ` apiVersion: apps/v1 kind: Deployment metadata: name: myAuditor spec: template: spec: containers: - name: myContainer ` // Initialize all the security auditors using default configuration allAuditors, err := all.Auditors(config.KubeauditConfig{}) if err != nil { log.Fatal(err) } // Initialize kubeaudit auditor, err := kubeaudit.New(allAuditors) if err != nil { log.Fatal(err) } // Run the audit in manifest mode report, err := auditor.AuditManifest("", strings.NewReader(manifest)) if err != nil { log.Fatal(err) } // Print the audit results to screen report.PrintResults() // Print the plan to screen. These are the steps that will be taken by calling "report.Fix()". fmt.Println("\nPlan:") report.PrintPlan(os.Stdout) // Print the fixed manifest to screen. Note that this leaves the original manifest unmodified. fmt.Println("\nFixed manifest:") err = report.Fix(os.Stdout) if err != nil { log.Fatal(err) } }
Output:
Example (AuditCluster) ¶
ExampleAuditCluster shows how to run kubeaudit in cluster mode (only works if kubeaudit is being run from a container insdie of a cluster)
package main import ( "github.com/elliotxx/kubeaudit" "github.com/elliotxx/kubeaudit/auditors/all" "github.com/elliotxx/kubeaudit/config" log "github.com/sirupsen/logrus" ) func main() { // Initialize all the security auditors using default configuration allAuditors, err := all.Auditors(config.KubeauditConfig{}) if err != nil { log.Fatal(err) } // Initialize kubeaudit auditor, err := kubeaudit.New(allAuditors) if err != nil { log.Fatal(err) } // Run the audit in cluster mode. Note this will fail if kubeaudit is not running within a cluster. report, err := auditor.AuditCluster(kubeaudit.AuditOptions{}) if err != nil { log.Fatal(err) } // Print the audit results to screen report.PrintResults() }
Output:
Example (AuditLocal) ¶
ExampleAuditLocal shows how to run kubeaudit in local mode
package main import ( "github.com/elliotxx/kubeaudit" "github.com/elliotxx/kubeaudit/auditors/all" "github.com/elliotxx/kubeaudit/config" log "github.com/sirupsen/logrus" ) func main() { // Initialize all the security auditors using default configuration allAuditors, err := all.Auditors(config.KubeauditConfig{}) if err != nil { log.WithError(err).Fatal("Error initializing all auditors") } // Initialize kubeaudit auditor, err := kubeaudit.New(allAuditors) if err != nil { log.Fatal(err) } // Run the audit in local mode report, err := auditor.AuditLocal("", "", kubeaudit.AuditOptions{}) if err != nil { log.Fatal(err) } // Print the audit results to screen report.PrintResults() }
Output:
Example (AuditorSubset) ¶
ExampleAuditorSubset shows how to run kubeaudit with a subset of auditors
package main import ( "strings" "github.com/elliotxx/kubeaudit" "github.com/elliotxx/kubeaudit/auditors/apparmor" "github.com/elliotxx/kubeaudit/auditors/image" log "github.com/sirupsen/logrus" ) func main() { // A sample Kubernetes manifest file manifest := ` apiVersion: apps/v1 kind: Deployment metadata: name: myAuditor spec: template: spec: containers: - name: myContainer ` // Initialize the auditors you want to use auditor, err := kubeaudit.New([]kubeaudit.Auditable{ apparmor.New(), image.New(image.Config{Image: "myimage:mytag"}), }) if err != nil { log.Fatal(err) } // Run the audit in the mode of your choosing. Here we use manifest mode. report, err := auditor.AuditManifest("", strings.NewReader(manifest)) if err != nil { log.Fatal(err) } // Print the audit results to screen report.PrintResults() }
Output:
Example (Config) ¶
ExampleConfig shows how to use a kubeaudit with a config file. A kubeaudit config can be used to specify which security auditors to run, and to specify configuration for those auditors.
package main import ( "os" "strings" "github.com/elliotxx/kubeaudit" "github.com/elliotxx/kubeaudit/auditors/all" "github.com/elliotxx/kubeaudit/config" log "github.com/sirupsen/logrus" ) func main() { configFile := "config/config.yaml" // A sample Kubernetes manifest file manifest := ` apiVersion: apps/v1 kind: Deployment metadata: name: myAuditor spec: template: spec: containers: - name: myContainer ` // Open the configuration file reader, err := os.Open(configFile) if err != nil { log.WithError(err).Fatal("Unable to open config file ", configFile) } // Load the config conf, err := config.New(reader) if err != nil { log.WithError(err).Fatal("Error parsing config file ", configFile) } // Initialize security auditors using the configuration auditors, err := all.Auditors(conf) if err != nil { log.Fatal(err) } // Initialize kubeaudit auditor, err := kubeaudit.New(auditors) if err != nil { log.Fatal(err) } // Run the audit in the mode of your choosing. Here we use manifest mode. report, err := auditor.AuditManifest("", strings.NewReader(manifest)) if err != nil { log.Fatal(err) } // Print the audit results to screen report.PrintResults() }
Output:
Example (CustomAuditor) ¶
ExampleCustomAuditor shows how to use a custom auditor
package main import ( "fmt" "strings" "github.com/elliotxx/kubeaudit" "github.com/elliotxx/kubeaudit/pkg/k8s" log "github.com/sirupsen/logrus" ) func NewCustomAuditor() kubeaudit.Auditable { return &myAuditor{} } // Your auditor must implement the Auditable interface, which requires only one method: Audit(). type myAuditor struct{} // The Audit function takes in a resource to audit and returns audit results for that resource. // // Params // // resource: Read-only. The resource to audit. // resources: Read-only. A reference to all resources. Can be used for context though most auditors don't need this. // // Return // // auditResults: The results for the audit. Each result can optionally include a PendingFix object to // define autofix behaviour (see below). func (a *myAuditor) Audit(resource k8s.Resource, _ []k8s.Resource) ([]*kubeaudit.AuditResult, error) { return []*kubeaudit.AuditResult{ { Auditor: "Awesome", Rule: "MyAudit", Severity: kubeaudit.Error, Message: "My custom error", PendingFix: &myAuditorFix{ newVal: "bye", }, }, }, nil } // To provide autofix behaviour for an audit result, implement the PendingFix interface. The PendingFix interface // has two methods: Plan() and Apply(). type myAuditorFix struct { newVal string } // The Plan method explains what fix will be applied by Apply(). // // Return // // plan: A human-friendly explanation of what Apply() will do func (f *myAuditorFix) Plan() string { return fmt.Sprintf("Set label 'hi' to '%s'", f.newVal) } // The Apply method applies a fix to a resource. // // Params // // resource: A reference to the resource that should be fixed. // // Return // // newResources: New resources created as part of the fix. Generally, it should not be necessary to create // new resources, only modify the passed in resource. func (f *myAuditorFix) Apply(resource k8s.Resource) []k8s.Resource { setLabel(resource, "hi", f.newVal) return nil } // This is just a helper function func setLabel(resource k8s.Resource, key, value string) { switch kubeType := resource.(type) { case *k8s.PodV1: kubeType.Labels[key] = value case *k8s.DeploymentV1: kubeType.Labels[key] = value } } // A sample Kubernetes manifest file var manifest = ` apiVersion: apps/v1 kind: Deployment metadata: name: myAuditor spec: template: spec: containers: - name: myContainer ` // ExampleCustomAuditor shows how to use a custom auditor func main() { // Initialize kubeaudit with your custom auditor auditor, err := kubeaudit.New([]kubeaudit.Auditable{NewCustomAuditor()}) if err != nil { log.Fatal(err) } // Run the audit in the mode of your choosing. Here we use manifest mode. report, err := auditor.AuditManifest("", strings.NewReader(manifest)) if err != nil { log.Fatal(err) } // Print the results to screen report.PrintResults() }
Output:
Example (PrintOptions) ¶
ExamplePrintOptions shows how to use different print options for printing audit results.
package main import ( "os" "github.com/elliotxx/kubeaudit" "github.com/elliotxx/kubeaudit/auditors/apparmor" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) func main() { auditor, err := kubeaudit.New([]kubeaudit.Auditable{apparmor.New()}) if err != nil { log.Fatal(err) } report, err := auditor.AuditLocal("", "", kubeaudit.AuditOptions{}) if err != nil { log.Fatal(err) } // Print the audit results to a file f, err := os.Create("output.txt") if err != nil { log.Fatal(err) } defer f.Close() defer os.Remove("output.txt") report.PrintResults(kubeaudit.WithWriter(f)) // Only print audit results with severity of Error (ignore info and warning) report.PrintResults(kubeaudit.WithMinSeverity(kubeaudit.Error)) // Print results as JSON report.PrintResults(kubeaudit.WithFormatter(&logrus.JSONFormatter{})) }
Output:
Index ¶
- Constants
- type AuditOptions
- type AuditResult
- type Auditable
- type KubeResource
- type Kubeaudit
- func (a *Kubeaudit) AuditCluster(options AuditOptions) (*Report, error)
- func (a *Kubeaudit) AuditLocal(configpath string, context string, options AuditOptions) (*Report, error)
- func (a *Kubeaudit) AuditManifest(manifestPath string, manifest io.Reader) (*Report, error)
- func (a *Kubeaudit) AuditSingleManifest(manifest io.Reader) (*Report, error)
- type Metadata
- type Option
- type PendingFix
- type PrintOption
- type Printer
- type Report
- func (r *Report) Fix(writer io.Writer) error
- func (r *Report) HasErrors() (errorsFound bool)
- func (r *Report) PrintPlan(writer io.Writer)
- func (r *Report) PrintResults(printOptions ...PrintOption)
- func (r *Report) RawResults() []Result
- func (r *Report) Results() []Result
- func (r *Report) ResultsWithMinSeverity(minSeverity SeverityLevel) []Result
- type Result
- type SeverityLevel
- type WorkloadResult
Examples ¶
Constants ¶
const ErrorUnsupportedResource = "Unsupported resource"
ErrorUnsupportedResource occurs when Kubeaudit doesn't know how to audit the resource
const RedundantAuditorOverride = "RedundantAuditorOverride"
RedundantAuditorOverride is the audit result name given when an override label is used to disable an auditor, but that auditor found no security issues so the label is redundant
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AuditOptions ¶
type AuditOptions = k8sinternal.ClientOptions
type AuditResult ¶
type AuditResult struct { Auditor string // Auditor name Rule string // Rule uniquely identifies a type of violation Severity SeverityLevel // Severity is one of Error, Warn, or Info Message string // Message is a human-readable description of the audit result PendingFix PendingFix // PendingFix is the fix that will be applied to automatically fix the security issue Metadata Metadata // Metadata includes additional context for an audit result FilePath string // Manifest file path }
AuditResult represents a potential security issue. There may be multiple AuditResults per resource and audit
func (*AuditResult) Fix ¶
func (result *AuditResult) Fix(resource k8s.Resource) (newResources []k8s.Resource)
func (*AuditResult) FixPlan ¶
func (result *AuditResult) FixPlan() (ok bool, plan string)
type Auditable ¶
type Auditable interface {
Audit(resource k8s.Resource, resources []k8s.Resource) ([]*AuditResult, error)
}
Auditable is an interface which is implemented by auditors
type KubeResource ¶
type KubeResource interface { // Object is a pointer to a Kubernetes resource. The resource may be modified by multiple auditors Object() k8s.Resource // Bytes is the original byte representation of the resource Bytes() []byte }
KubeResource is a wrapper around a Kubernetes object
type Kubeaudit ¶
type Kubeaudit struct {
// contains filtered or unexported fields
}
Kubeaudit provides functions to audit and fix Kubernetes manifests
func (*Kubeaudit) AuditCluster ¶
func (a *Kubeaudit) AuditCluster(options AuditOptions) (*Report, error)
AuditCluster audits the Kubernetes resources found in the cluster in which Kubeaudit is running
func (*Kubeaudit) AuditLocal ¶
func (a *Kubeaudit) AuditLocal(configpath string, context string, options AuditOptions) (*Report, error)
AuditLocal audits the Kubernetes resources found in the provided Kubernetes config file
func (*Kubeaudit) AuditManifest ¶
AuditManifest audits the Kubernetes resources in the provided manifest
type Option ¶
Option is used to specify the behaviour of Kubeaudit Auditor
func WithLogger ¶
WithLogger specifies the log formatter to use
type PendingFix ¶
type PendingFix interface { // Plan returns a human-readable description of what Apply() will do Plan() string // Apply applies the proposed fix to the resource and returns any new resources that were created. Note that // Apply is expected to modify the passed in resource Apply(k8s.Resource) []k8s.Resource }
PendingFix includes the logic to automatically fix the issues caught by auditing
type PrintOption ¶
type PrintOption func(p *Printer)
func WithColor ¶
func WithColor(color bool) PrintOption
WithColor specifies whether or not to colorize output. You will likely want to set this to false if not writing to standard out.
func WithFormatter ¶
func WithFormatter(formatter log.Formatter) PrintOption
WithFormatter sets a logrus formatter to use to format results.
func WithMinSeverity ¶
func WithMinSeverity(minSeverity SeverityLevel) PrintOption
WithMinSeverity sets the minimum severity of results that will be printed.
func WithWriter ¶
func WithWriter(writer io.Writer) PrintOption
WithWriter sets the writer where results will be written to.
type Printer ¶
type Printer struct {
// contains filtered or unexported fields
}
func NewPrinter ¶
func NewPrinter(opts ...PrintOption) Printer
func (*Printer) PrintReport ¶
type Report ¶
type Report struct {
// contains filtered or unexported fields
}
Report contains the results after auditing
func (*Report) Fix ¶
Fix tries to automatically patch any security concerns and writes the resulting manifest to the provided writer. Only applies when audit was performed on a manifest (not local or cluster)
func (*Report) PrintPlan ¶
PrintPlan writes the actions that will be performed by the Fix() function in a human-readable way to the provided writer. Only applies when audit was performed on a manifest (not local or cluster)
func (*Report) PrintResults ¶
func (r *Report) PrintResults(printOptions ...PrintOption)
PrintResults writes the audit results to the specified writer. Defaults to printing results to stdout
func (*Report) RawResults ¶
RawResults returns all of the results for each Kubernetes resource, including ones that had no audit results. Generally, you will want to use Results() instead.
func (*Report) ResultsWithMinSeverity ¶
func (r *Report) ResultsWithMinSeverity(minSeverity SeverityLevel) []Result
ResultsWithMinSeverity returns the audit results for each Kubernetes resource with a minimum severity
type Result ¶
type Result interface { GetResource() KubeResource GetAuditResults() []*AuditResult }
Result contains the audit results for a single Kubernetes resource
type SeverityLevel ¶
type SeverityLevel int
const ( // Info is used for informational audit results where no action is required Info SeverityLevel = 0 // Warn is used for audit results where there may be security concerns. If an auditor is disabled for a resource // using an override label, the audit results will be warnings instead of errors. Kubeaudit will NOT attempt to // fix these Warn SeverityLevel = 1 // Error is used for audit results where action is required. Kubeaudit will attempt to fix these Error SeverityLevel = 2 )
AuditResult severity levels. They also correspond to log levels
func (SeverityLevel) String ¶
func (s SeverityLevel) String() string
type WorkloadResult ¶
type WorkloadResult struct { Resource KubeResource AuditResults []*AuditResult }
Implements Result
func (*WorkloadResult) GetAuditResults ¶
func (wlResult *WorkloadResult) GetAuditResults() []*AuditResult
func (*WorkloadResult) GetResource ¶
func (wlResult *WorkloadResult) GetResource() KubeResource