From abac30ad09eae01ed198452b3f2c8b1c491c8eba Mon Sep 17 00:00:00 2001 From: Dani Date: Thu, 29 Oct 2020 11:07:39 -0400 Subject: [PATCH] Autofix with config (#313) * autofix takes config file --- README.md | 51 ++++++++++++++++++++++++++++++- cmd/commands/all.go | 20 ++++++------ cmd/commands/autofix.go | 25 ++++++++++++--- docs/all.md | 68 +++++++++++------------------------------ docs/autofix.md | 11 +++++++ 5 files changed, 110 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index e189139d..8e8fc6d5 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,12 @@ To write the fixed manifest to a new file instead of modifying the source file, kubeaudit autofix -f "/path/to/manifest.yml" -o "/path/to/fixed" ``` +To fix a manifest based on custom rules specified on a kubeaudit config file, use the `-k/--kconfig` flag. + +``` +kubeaudit autofix -k "/path/to/kubeaudit-config.yml" -f "/path/to/manifest.yml" -o "/path/to/fixed" +``` + ### Cluster Mode Kubeaudit can detect if it is running within a container in a cluster. If so, it will try to audit all Kubernetes resources in that cluster: @@ -222,7 +228,50 @@ Auditors can also be run individually. ## Configuration File -Kubeaudit can be used with a configuration file instead of flags. See the [all command](docs/all.md). +The kubeaudit config can be used for two things: + +1. Enabling only some auditors +1. Specifying configuration for auditors + +Any configuration that can be specified using flags for the individual auditors can be represented using the config. + +The config has the following format: + +```yaml +enabledAuditors: + # Auditors are enabled by default if they are not explicitly set to "false" + apparmor: false + asat: false + capabilities: true + hostns: true + image: true + limits: true + mountds: true + netpols: true + nonroot: true + privesc: true + privileged: true + rootfs: true + seccomp: true +auditors: + capabilities: + # If no capabilities are specified and the 'capabilities' auditor is enabled, + # a list of recommended capabilities to drop is used + drop: ['AUDIT_WRITE', 'CHOWN'] + image: + # If no image is specified and the 'image' auditor is enabled, WARN results + # will be generated for containers which use an image without a tag + image: 'myimage:mytag' + limits: + # If no limits are specified and the 'limits' auditor is enabled, WARN results + # will be generated for containers which have no cpu or memory limits specified + cpu: '750m' + memory: '500m' +``` + +For more details about each auditor, including a description of the auditor-specific configuration in the config, see the [Auditor Docs](#auditors). + +**Note**: The kubeaudit config is not the same as the kubeconfig file specified with the `-c/--kubeconfig` flag, which refers to the Kubernetes config file (see [Local Mode](/README.md#local-mode)). Also note that only the `all` and `autofix` commands support using a kubeaudit config. It will not work with other commands. ## Override Errors diff --git a/cmd/commands/all.go b/cmd/commands/all.go index b3e0168c..c382444a 100644 --- a/cmd/commands/all.go +++ b/cmd/commands/all.go @@ -14,17 +14,17 @@ var auditAllConfig struct { } func auditAll(cmd *cobra.Command, args []string) { - conf := loadConfigFromFile(auditAllConfig.configFile) + conf := loadKubeAuditConfigFromFile(auditAllConfig.configFile) // Config options set via flags override the config file conf = setConfigFromFlags(cmd, conf) - allAuditors, err := all.Auditors(conf) + auditors, err := all.Auditors(conf) if err != nil { log.WithError(err).Fatal("Error creating auditors") } - runAudit(allAuditors...)(cmd, args) + runAudit(auditors...)(cmd, args) } func setConfigFromFlags(cmd *cobra.Command, conf config.KubeauditConfig) config.KubeauditConfig { @@ -50,19 +50,19 @@ func setConfigFromFlags(cmd *cobra.Command, conf config.KubeauditConfig) config. return conf } -func loadConfigFromFile(configFile string) config.KubeauditConfig { - if auditAllConfig.configFile == "" { +func loadKubeAuditConfigFromFile(configFile string) config.KubeauditConfig { + if configFile == "" { return config.KubeauditConfig{} } - reader, err := os.Open(auditAllConfig.configFile) + reader, err := os.Open(configFile) if err != nil { - log.WithError(err).Fatal("Unable to open config file ", auditAllConfig.configFile) + log.WithError(err).Fatal("Unable to open config file ", configFile) } conf, err := config.New(reader) if err != nil { - log.WithError(err).Fatal("Error parsing config file ", auditAllConfig.configFile) + log.WithError(err).Fatal("Error parsing config file ", configFile) } return conf @@ -74,7 +74,9 @@ var auditAllCmd = &cobra.Command{ Long: `Run all audits Example usage: -kubeaudit all -f /path/to/yaml`, +kubeaudit all -f /path/to/yaml +kubeaudit all -k /path/to/kubeaudit-config.yaml /path/to/yaml +`, Run: auditAll, } diff --git a/cmd/commands/autofix.go b/cmd/commands/autofix.go index 6d90771b..11ae2551 100644 --- a/cmd/commands/autofix.go +++ b/cmd/commands/autofix.go @@ -4,18 +4,29 @@ import ( "io" "os" + "github.com/Shopify/kubeaudit/auditors/all" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var autofixConfig struct { - outFile string + outFile string + kubeauditConfigFile string } func autofix(cmd *cobra.Command, args []string) { - report := getReport() + conf := loadKubeAuditConfigFromFile(autofixConfig.kubeauditConfigFile) + + conf = setConfigFromFlags(cmd, conf) + + auditors, err := all.Auditors(conf) + + if err != nil { + log.WithError(err).Fatal("Error creating auditors") + } + + report := getReport(auditors...) - var err error var f io.Writer if autofixConfig.outFile != "" { f, err = os.Create(autofixConfig.outFile) @@ -40,15 +51,19 @@ var autofixCmd = &cobra.Command{ Short: "Automagically make a manifest secure", Long: `This command automatically fixes all identified security issues for a given manifest (ie. all ERROR results generated by 'kubeaudit all'). If no output file is specified using the -o flag, -the source manifest will be modified. +the source manifest will be modified. You can use the -k flag followed by the path to the kubeaudit +config file to run fixes based on custom rules. Example usage: kubeaudit autofix -f /path/to/yaml -kubeaudit autofix -f /path/to/yaml -o /path/for/fixed/yaml`, +kubeaudit autofix -f /path/to/yaml -o /path/for/fixed/yaml +kubeaudit autofix -k /path/to/kubeaudit-config.yaml -f /path/to/yaml +`, Run: autofix, } func init() { RootCmd.AddCommand(autofixCmd) autofixCmd.Flags().StringVarP(&autofixConfig.outFile, "outfile", "o", "", "File to write fixed manifest to") + autofixCmd.Flags().StringVarP(&autofixConfig.kubeauditConfigFile, "kconfig", "k", "", "Path to kubeaudit config") } diff --git a/docs/all.md b/docs/all.md index 82b61393..eb65b91a 100644 --- a/docs/all.md +++ b/docs/all.md @@ -10,57 +10,21 @@ kubeaudit all [flags] ## Flags -| Short | Long | Description | Default | -| :------ | :--------- | :---------------------------------------- | :--------------------------------------- | -| -k | --kconfig | Path to kubeaudit config | | +| Short | Long | Description | Default | +| :---- | :-------- | :----------------------- | :------ | +| -k | --kconfig | Path to kubeaudit config | | Also see [Global Flags](/README.md#global-flags) ### Kubeaudit Config -The kubeaudit config can be used for two things: -1. Enabling only some auditors -1. Specifying configuration for auditors +A kubeaudit config file can be used instead of flags. -Any configuration that can be specified using flags for the individual auditors can be represented using the config. - -The config has the following format: - -```yaml -enabledAuditors: - # Auditors are enabled by default if they are not explicitly set to "false" - apparmor: false - asat: false - capabilities: true - hostns: true - image: true - limits: true - mountds: true - netpols: true - nonroot: true - privesc: true - privileged: true - rootfs: true - seccomp: true -auditors: - capabilities: - # If no capabilities are specified and the 'capabilities' auditor is enabled, - # a list of recommended capabilities to drop is used - drop: ["AUDIT_WRITE", "CHOWN"] - image: - # If no image is specified and the 'image' auditor is enabled, WARN results - # will be generated for containers which use an image without a tag - image: "myimage:mytag" - limits: - # If no limits are specified and the 'limits' auditor is enabled, WARN results - # will be generated for containers which have no cpu or memory limits specified - cpu: "750m" - memory: "500m" +``` +kubeaudit all -k "/path/to/kubeaudit-config.yml" -f "/path/to/manifest.yml" ``` -For more details about each auditor, including a description of the auditor-specific configuration in the config, see the [Auditor Docs](/README.md#auditors). - -**Note**: The kubeaudit config is not the same as the kubeconfig file specified with the `-c/--kubeconfig` flag, which refers to the Kubernetes config file (see [Local Mode](/README.md#local-mode)). Also note that only the `all` command supports using a kubeaudit config. It will not work with other commands. +Also see [Configuration File](/README.md#configuration-file) ## Examples @@ -161,18 +125,20 @@ $ kubeaudit all -f "internal/test/fixtures/all_resources/deployment-apps-v1.yml" ### Example with Kubeaudit Config Consider the following kubeaudit config `config.yaml` + ```yaml enabledAuditors: - # Auditors are enabled by default if they are not explicitly set to "false" - hostns: false - image: false - limits: false + # Auditors are enabled by default if they are not explicitly set to "false" + hostns: false + image: false + limits: false auditors: - capabilities: - drop: ["AUDIT_WRITE", "CHOWN"] + capabilities: + drop: ['AUDIT_WRITE', 'CHOWN'] ``` The config can be passed to the `all` command using the `-k/--kconfig` flag: + ``` $ kubeaudit all -k "config.yaml" -f "auditors/all/fixtures/audit_all_v1.yml" ``` @@ -180,6 +146,7 @@ $ kubeaudit all -k "config.yaml" -f "auditors/all/fixtures/audit_all_v1.yml" ### Example with Flags The behaviour of the `all` command can also be customized by using flags. The `all` command supports all flags supported by invididual auditors (see the individual [auditor docs](/README.md#auditors) for all the flags). For example, the `caps` auditor supports specifying capabilities to drop with the `--drop/-d` flag so this flag can be used with the `all` command: + ``` kubeaudit all -f "auditors/all/fixtures/audit_all_v1.yml" --drop "AUDIT_WRITE" ``` @@ -187,11 +154,13 @@ kubeaudit all -f "auditors/all/fixtures/audit_all_v1.yml" --drop "AUDIT_WRITE" ### Example with Kubeaudit Config and Flags Passing flags in addition to the config will override the corresponding fields from the config. For example, if the capabilities to drop are specified with the `--drop/-d` flag: + ``` kubeaudit all -f "auditors/all/fixtures/audit_all_v1.yml" --drop "AUDIT_WRITE" ``` And they are also specified in the Kubeaudit config file: + ```yaml auditors: capabilities: @@ -199,4 +168,3 @@ auditors: ``` The capabilities specified by the flag will take precedence over those specified in the config file resulting in only `AUDIT_WRITE` being dropped. - diff --git a/docs/autofix.md b/docs/autofix.md index 6387d1ca..89a21a1a 100644 --- a/docs/autofix.md +++ b/docs/autofix.md @@ -15,6 +15,7 @@ kubeaudit autofix -f [manifest] [flags] | Short | Long | Description | Default | | :------ | :--------- | :---------------------------------------- | :--------------------------------------- | | -o | --outfile | File to write fixed manifest to | | +| -k | --kconfig | Path to kubeaudit config file | | Also see [Global Flags](/README.md#global-flags) @@ -263,3 +264,13 @@ To write the fixed manifest to a different file, use the `--outfile/-o` flag: ``` kubeaudit autofix -f "manifest.yml" -o "fixed.yaml" ``` + +### Using Custom Rules with Kubeaudit Config File + +To fix a manifest based on custom rules specified on a kubeaudit config file (e.g disable some auditors), use the `-k/--kconfig` flag. + +``` +kubeaudit autofix -k "/path/to/kubeaudit-config.yml" -f "/path/to/manifest.yml" -o "/path/to/fixed" +``` + +Also see [Configuration File](/README.md#configuration-file) \ No newline at end of file