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")
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("")
Get the results ¶
To print the results in a human readable way:
report.PrintResults(os.Stdout, kubeaudit.Info, nil)
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(os.Stdout, kubeaudit.Error, nil)
// 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)
}
}
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 (
"os"
"github.com/Shopify/kubeaudit"
"github.com/Shopify/kubeaudit/auditors/all"
"github.com/Shopify/kubeaudit/config"
"github.com/Shopify/kubeaudit/internal/k8s"
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(k8s.ClientOptions{})
if err != nil {
log.Fatal(err)
}
// Print the audit results to screen
report.PrintResults(os.Stdout, kubeaudit.Info, nil)
}
Example (AuditLocal) ¶
ExampleAuditLocal shows how to run kubeaudit in local mode
package main
import (
"os"
"github.com/Shopify/kubeaudit"
"github.com/Shopify/kubeaudit/auditors/all"
"github.com/Shopify/kubeaudit/config"
"github.com/Shopify/kubeaudit/internal/k8s"
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("", k8s.ClientOptions{})
if err != nil {
log.Fatal(err)
}
// Print the audit results to screen
report.PrintResults(os.Stdout, kubeaudit.Info, nil)
}
Example (AuditorSubset) ¶
ExampleAuditorSubset shows how to run kubeaudit with a subset of auditors
// 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(os.Stdout, kubeaudit.Info, &log.JSONFormatter{})
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.
configFile := "config/config.yaml"
// 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(os.Stdout, kubeaudit.Error, nil)
Example (CustomAuditor) ¶
ExampleCustomAuditor shows how to use a custom auditor
package main
import (
"fmt"
"os"
"strings"
"github.com/Shopify/kubeaudit"
"github.com/Shopify/kubeaudit/k8stypes"
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.
//
// 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 k8stypes.Resource, _ []k8stypes.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 k8stypes.Resource) []k8stypes.Resource {
setLabel(resource, "hi", f.newVal)
return nil
}
// This is just a helper function
func setLabel(resource k8stypes.Resource, key, value string) {
switch kubeType := resource.(type) {
case *k8stypes.PodV1:
kubeType.Labels[key] = value
case *k8stypes.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(os.Stdout, kubeaudit.Info, nil)
}
Index ¶
- Constants
- type AuditResult
- type Auditable
- type KubeResource
- type Kubeaudit
- type Metadata
- type Option
- type PendingFix
- 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(writer io.Writer, minSeverity int, formatter log.Formatter)
- func (r *Report) RawResults() []Result
- func (r *Report) Results() []Result
- type Result
Examples ¶
Constants ¶
const ( // Info is used for informational audit results where no action is required Info = iota // 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 // Error is used for audit results where action is required. Kubeaudit will attempt to fix these Error )
AuditResult severity levels. They also correspond to log levels
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 AuditResult ¶
type AuditResult struct {
Name string // Name uniquely identifies a type of audit result
Severity int // 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 k8stypes.Resource) (newResources []k8stypes.Resource)
func (*AuditResult) FixPlan ¶
func (result *AuditResult) FixPlan() (ok bool, plan string)
type Auditable ¶
type Auditable interface {
Audit(resource k8stypes.Resource, resources []k8stypes.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() k8stypes.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 k8s.ClientOptions) (*Report, error)
AuditCluster audits the Kubernetes resources found in the cluster in which Kubeaudit is running
func (*Kubeaudit) AuditLocal ¶
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(k8stypes.Resource) []k8stypes.Resource
}
PendingFix includes the logic to automatically fix the issues caught by auditing
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 ¶
PrintResults writes the audit results with a severity greater than or matching minSeverity in a human-readable way to the provided writer
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.
type Result ¶
type Result interface {
GetResource() KubeResource
GetAuditResults() []*AuditResult
}
Result contains the audit results for a single Kubernetes resource
