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/Shopify/kubeaudit#auditors.
To initialize all available auditors:
import "github.com/Shopify/kubeaudit/auditors/all" auditors, err := all.Auditors(config.KubeauditConfig{})
Or, to initialize specific auditors, import each one:
import ( "github.com/Shopify/kubeaudit/auditors/apparmor" "github.com/Shopify/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/Shopify/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/Shopify/kubeaudit" "github.com/Shopify/kubeaudit/auditors/all" "github.com/Shopify/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/Shopify/kubeaudit" "github.com/Shopify/kubeaudit/auditors/all" "github.com/Shopify/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/Shopify/kubeaudit" "github.com/Shopify/kubeaudit/auditors/all" "github.com/Shopify/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/Shopify/kubeaudit" "github.com/Shopify/kubeaudit/auditors/apparmor" "github.com/Shopify/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/Shopify/kubeaudit" "github.com/Shopify/kubeaudit/auditors/all" "github.com/Shopify/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/Shopify/kubeaudit" "github.com/Shopify/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/Shopify/kubeaudit" "github.com/Shopify/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
- 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 ΒΆ added in v0.17.1
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
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 ΒΆ added in v0.11.0
type PrintOption func(p *Printer)
func WithColor ΒΆ added in v0.17.1
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 ΒΆ added in v0.11.0
func WithFormatter(formatter log.Formatter) PrintOption
WithFormatter sets a logrus formatter to use to format results.
func WithMinSeverity ΒΆ added in v0.11.0
func WithMinSeverity(minSeverity SeverityLevel) PrintOption
WithMinSeverity sets the minimum severity of results that will be printed.
func WithWriter ΒΆ added in v0.11.0
func WithWriter(writer io.Writer) PrintOption
WithWriter sets the writer where results will be written to.
type Printer ΒΆ added in v0.11.0
type Printer struct {
// contains filtered or unexported fields
}
func NewPrinter ΒΆ added in v0.11.0
func NewPrinter(opts ...PrintOption) Printer
func (*Printer) PrintReport ΒΆ added in v0.11.0
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) HasErrors ΒΆ added in v0.10.0
HasErrors returns true if any findings have the level of Error
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 ΒΆ added in v0.11.0
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 ΒΆ added in v0.11.0
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 ΒΆ added in v0.11.0
func (s SeverityLevel) String() string
type WorkloadResult ΒΆ added in v0.20.0
type WorkloadResult struct { Resource KubeResource AuditResults []*AuditResult }
Implements Result
func (*WorkloadResult) GetAuditResults ΒΆ added in v0.20.0
func (wlResult *WorkloadResult) GetAuditResults() []*AuditResult
func (*WorkloadResult) GetResource ΒΆ added in v0.20.0
func (wlResult *WorkloadResult) GetResource() KubeResource