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{ { Name: "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
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 { Name string // Name uniquely identifies a type of audit result 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 }
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