Repository: aquasecurity/kube-bench
Pull request #736 (2020-10-12 00:37:39)

Allow for skip to be defined on a group-level skipping all checks inside
This fixes issue #649 allowing groups to be defined to be skipped. this is done by setting 'Skip' on the group to true. When checks are run this will then set the state of any checks within that group to info (the check is still technically run but just overridden to be INFO as I wasn't sure on what the desired behaviour here was, we could just skip the check entirely and not run and just set it to INFO).

Please let me know if there are any additional changes you want done to this!

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/kube-bench/pull/736?src=pr&el=h1) Report
> Merging [#736](https://codecov.io/gh/aquasecurity/kube-bench/pull/736?src=pr&el=desc) into [master](https://codecov.io/gh/aquasecurity/kube-bench/commit/58bea9c89b9be43ebdf76de256d916a608df43c4?el=desc) will **increase** coverage by `0.52%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/aquasecurity/kube-bench/pull/736/graphs/tree.svg?width=650&height=150&src=pr&token=MVaDEmdgi9)](https://codecov.io/gh/aquasecurity/kube-bench/pull/736?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #736      +/-   ##
==========================================
+ Coverage   63.31%   63.83%   +0.52%     
==========================================
  Files          12       12              
  Lines        1044     1048       +4     
==========================================
+ Hits          661      669       +8     
+ Misses        344      340       -4     
  Partials       39       39              
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/kube-bench/pull/736?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [check/controls.go](https://codecov.io/gh/aquasecurity/kube-bench/pull/736/diff?src=pr&el=tree#diff-Y2hlY2svY29udHJvbHMuZ28=) | `75.86% <100.00%> (+5.98%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/aquasecurity/kube-bench/pull/736?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/aquasecurity/kube-bench/pull/736?src=pr&el=footer). Last update [58bea9c...9c261fb](https://codecov.io/gh/aquasecurity/kube-bench/pull/736?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/cfg/cis-1.5/master.yaml b/cfg/cis-1.5/master.yaml
index 3881fae..8f9c1ad 100644
--- a/cfg/cis-1.5/master.yaml
+++ b/cfg/cis-1.5/master.yaml
@@ -223,7 +223,7 @@ groups:
 
       - id: 1.1.15
         text: "Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Scored)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/scheduler.conf; then stat -c permissions=%a /etc/kubernetes/scheduler.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c permissions=%a $schedulerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "permissions"
@@ -234,12 +234,12 @@ groups:
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chmod 644 /etc/kubernetes/scheduler.conf
+          chmod 644 $schedulerkubeconfig
         scored: true
 
       - id: 1.1.16
         text: "Ensure that the scheduler.conf file ownership is set to root:root (Scored)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/scheduler.conf; then stat -c %U:%G /etc/kubernetes/scheduler.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c %U:%G $schedulerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "root:root"
@@ -250,12 +250,12 @@ groups:
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chown root:root /etc/kubernetes/scheduler.conf
+          chown root:root $schedulerkubeconfig
         scored: true
 
       - id: 1.1.17
         text: "Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Scored)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/controller-manager.conf; then stat -c permissions=%a /etc/kubernetes/controller-manager.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c permissions=%a $controllermanagerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "permissions"
@@ -266,12 +266,12 @@ groups:
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chmod 644 /etc/kubernetes/controller-manager.conf
+          chmod 644 $controllermanagerkubeconfig
         scored: true
 
       - id: 1.1.18
         text: "Ensure that the controller-manager.conf file ownership is set to root:root (Scored)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/controller-manager.conf; then stat -c %U:%G /etc/kubernetes/controller-manager.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c %U:%G $controllermanagerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "root:root"
@@ -282,7 +282,7 @@ groups:
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chown root:root /etc/kubernetes/controller-manager.conf
+          chown root:root $controllermanagerkubeconfig
         scored: true
 
       - id: 1.1.19
@@ -908,7 +908,7 @@ groups:
           test_items:
             - flag: "--tls-cipher-suites"
               compare:
-                op: has
+                op: valid_elements
                 value: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256"
               set: true
         remediation: |
diff --git a/cfg/cis-1.6/master.yaml b/cfg/cis-1.6/master.yaml
index 8f07ced..fa23948 100644
--- a/cfg/cis-1.6/master.yaml
+++ b/cfg/cis-1.6/master.yaml
@@ -196,7 +196,7 @@ groups:
 
       - id: 1.1.15
         text: "Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Automated)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/scheduler.conf; then stat -c permissions=%a /etc/kubernetes/scheduler.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c permissions=%a $schedulerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "permissions"
@@ -206,24 +206,24 @@ groups:
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chmod 644 /etc/kubernetes/scheduler.conf
+          chmod 644 $schedulerkubeconfig
         scored: true
 
       - id: 1.1.16
         text: "Ensure that the scheduler.conf file ownership is set to root:root (Automated)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/scheduler.conf; then stat -c %U:%G /etc/kubernetes/scheduler.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c %U:%G $schedulerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "root:root"
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chown root:root /etc/kubernetes/scheduler.conf
+          chown root:root $schedulerkubeconfig
         scored: true
 
       - id: 1.1.17
         text: "Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Automated)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/controller-manager.conf; then stat -c permissions=%a /etc/kubernetes/controller-manager.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c permissions=%a $controllermanagerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "permissions"
@@ -233,19 +233,19 @@ groups:
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chmod 644 /etc/kubernetes/controller-manager.conf
+          chmod 644 $controllermanagerkubeconfig
         scored: true
 
       - id: 1.1.18
         text: "Ensure that the controller-manager.conf file ownership is set to root:root (Automated)"
-        audit: "/bin/sh -c 'if test -e /etc/kubernetes/controller-manager.conf; then stat -c %U:%G /etc/kubernetes/controller-manager.conf; fi'"
+        audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c %U:%G $controllermanagerkubeconfig; fi'"
         tests:
           test_items:
             - flag: "root:root"
         remediation: |
           Run the below command (based on the file location on your system) on the master node.
           For example,
-          chown root:root /etc/kubernetes/controller-manager.conf
+          chown root:root $controllermanagerkubeconfig
         scored: true
 
       - id: 1.1.19
@@ -832,7 +832,7 @@ groups:
           test_items:
             - flag: "--tls-cipher-suites"
               compare:
-                op: has
+                op: valid_elements
                 value: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256"
         remediation: |
           Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
diff --git a/cfg/config.yaml b/cfg/config.yaml
index 7170877..b31cab1 100644
--- a/cfg/config.yaml
+++ b/cfg/config.yaml
@@ -46,6 +46,10 @@ master:
       - /var/snap/kube-scheduler/current/args
       - /var/snap/microk8s/current/args/kube-scheduler
     defaultconf: /etc/kubernetes/manifests/kube-scheduler.yaml
+    kubeconfig:
+      - /etc/kubernetes/scheduler.conf
+    defaultkubeconfig:
+      - /etc/kubernetes/scheduler.conf
 
   controllermanager:
     bins:
@@ -61,6 +65,10 @@ master:
       - /var/snap/kube-controller-manager/current/args
       - /var/snap/microk8s/current/args/kube-controller-manager
     defaultconf: /etc/kubernetes/manifests/kube-controller-manager.yaml
+    kubeconfig:
+      - /etc/kubernetes/controller-manager.conf
+    defaultkubeconfig:
+      - /etc/kubernetes/controller-manager.conf
 
   etcd:
     optional: true
diff --git a/check/check.go b/check/check.go
index aa44a00..463afa8 100644
--- a/check/check.go
+++ b/check/check.go
@@ -39,6 +39,9 @@ const (
 	// INFO informational message
 	INFO State = "INFO"
 
+	// SKIP for when a check should be skipped.
+	SKIP = "skip"
+
 	// MASTER a master node
 	MASTER NodeType = "master"
 	// NODE a node
@@ -111,7 +114,7 @@ func (c *Check) run() State {
 	}
 
 	// If check type is skip, force result to INFO
-	if c.Type == "skip" {
+	if c.Type == SKIP {
 		c.Reason = "Test marked as skip"
 		c.State = INFO
 		return c.State
diff --git a/check/controls.go b/check/controls.go
index 1b36dee..992b78d 100644
--- a/check/controls.go
+++ b/check/controls.go
@@ -38,6 +38,7 @@ type Controls struct {
 // Group is a collection of similar checks.
 type Group struct {
 	ID     string   `yaml:"id" json:"section"`
+	Skip   bool     `yaml:"skip" json:"skip"`
 	Pass   int      `json:"pass"`
 	Fail   int      `json:"fail"`
 	Warn   int      `json:"warn"`
@@ -86,7 +87,13 @@ func (controls *Controls) RunChecks(runner Runner, filter Predicate) Summary {
 				continue
 			}
 
+			// propagate skip type to check if set at the group level.
+			if group.Skip {
+				check.Type = SKIP
+			}
+
 			state := runner.Run(check)
+
 			check.TestInfo = append(check.TestInfo, check.Remediation)
 
 			// Check if we have already added this checks group.
@@ -95,6 +102,7 @@ func (controls *Controls) RunChecks(runner Runner, filter Predicate) Summary {
 				w := &Group{
 					ID:     group.ID,
 					Text:   group.Text,
+					Skip:   group.Skip,
 					Checks: []*Check{},
 				}
 


Test patch:
diff --git a/check/controls_test.go b/check/controls_test.go
index fd49686..0d4cee6 100644
--- a/check/controls_test.go
+++ b/check/controls_test.go
@@ -95,8 +95,36 @@ groups:
 
 }
 
-func TestControls_RunChecks(t *testing.T) {
 
+func TestControls_RunChecks_Skipped(t *testing.T) {
+	t.Run("Should run checks matching the filter and update summaries", func(t *testing.T) {
+		// given
+		normalRunner := &defaultRunner{}
+		// and
+		in := []byte(`
+---
+type: "master"
+groups:
+- id: G1
+  skip: true
+  checks:
+  - id: G1/C1
+`)
+		controls, err := NewControls(MASTER, in)
+		assert.NoError(t, err)
+
+		var allChecks Predicate = func(group *Group, c *Check) bool {
+			return true
+		}
+		controls.RunChecks(normalRunner, allChecks)
+
+		G1 := controls.Groups[0]
+		assertEqualGroupSummary(t, 0, 0, 1, 0, G1)
+	})
+
+}
+
+func TestControls_RunChecks(t *testing.T) {
 	t.Run("Should run checks matching the filter and update summaries", func(t *testing.T) {
 		// given
 		runner := new(mockRunner)