From 13193d75b0e27e6728d6f85307d8888e7da3d495 Mon Sep 17 00:00:00 2001
From: Roberto Rojas <robertojrojas@gmail.com>
Date: Fri, 13 Dec 2019 10:09:30 -0500
Subject: [PATCH] Fixes Issue #535 (#537)

* isEtcd should not run on openshift 3.10/3.11

* adds openssl

* fixed tests

* fixes bugs

* adds isEtcd tests
---
 Dockerfile             |  5 +++
 cfg/config.yaml        |  3 --
 cfg/node_only.yaml     | 13 ++++++-
 cfg/rh-0.7/config.yaml |  2 +
 cmd/common.go          |  1 +
 cmd/common_test.go     | 86 +++++++++++++++++++++++++++++++++++++++---
 cmd/root.go            |  4 +-
 7 files changed, 103 insertions(+), 11 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 518e831..eccd82b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,6 +12,11 @@ WORKDIR /opt/kube-bench/
 # add GNU ps for -C, -o cmd, and --no-headers support
 # https://github.com/aquasecurity/kube-bench/issues/109
 RUN apk --no-cache add procps
+
+# Openssl is used by OpenShift tests
+# https://github.com/aquasecurity/kube-bench/issues/535
+RUN apk --no-cache add openssl
+
 COPY --from=build /go/bin/kube-bench /usr/local/bin/kube-bench
 COPY entrypoint.sh .
 COPY cfg/ cfg/
diff --git a/cfg/config.yaml b/cfg/config.yaml
index 71f1e45..0c20d6d 100644
--- a/cfg/config.yaml
+++ b/cfg/config.yaml
@@ -25,7 +25,6 @@ master:
       - "hyperkube apiserver"
       - "hyperkube kube-apiserver"
       - "apiserver"
-      - "openshift start master api"
     confs:
       - /etc/kubernetes/manifests/kube-apiserver.yaml
       - /etc/kubernetes/manifests/kube-apiserver.manifest
@@ -38,7 +37,6 @@ master:
       - "hyperkube scheduler"
       - "hyperkube kube-scheduler"
       - "scheduler"
-      - "openshift start master controllers"
     confs:
       - /etc/kubernetes/manifests/kube-scheduler.yaml
       - /etc/kubernetes/manifests/kube-scheduler.manifest
@@ -52,7 +50,6 @@ master:
       - "hyperkube controller-manager"
       - "hyperkube kube-controller-manager"
       - "controller-manager"
-      - "openshift start master controllers"
     confs:
       - /etc/kubernetes/manifests/kube-controller-manager.yaml
       - /etc/kubernetes/manifests/kube-controller-manager.manifest
diff --git a/cfg/node_only.yaml b/cfg/node_only.yaml
index c27cf58..62351ae 100644
--- a/cfg/node_only.yaml
+++ b/cfg/node_only.yaml
@@ -59,4 +59,15 @@ node:
     svc:
       - "/lib/systemd/system/kube-proxy.service"
     defaultconf: /etc/kubernetes/addons/kube-proxy-daemonset.yaml
-    defaultkubeconfig: "/etc/kubernetes/proxy.conf"
\ No newline at end of file
+    defaultkubeconfig: "/etc/kubernetes/proxy.conf"
+
+version_mapping:
+  "1.11": "cis-1.3"
+  "1.12": "cis-1.3"
+  "1.13": "cis-1.4"
+  "1.14": "cis-1.4"
+  "1.15": "cis-1.5"
+  "1.16": "cis-1.5"
+  "1.17": "cis-1.5"
+  "ocp-3.10": "rh-0.7"
+  "ocp-3.11": "rh-0.7"
\ No newline at end of file
diff --git a/cfg/rh-0.7/config.yaml b/cfg/rh-0.7/config.yaml
index b76332d..289c512 100644
--- a/cfg/rh-0.7/config.yaml
+++ b/cfg/rh-0.7/config.yaml
@@ -10,12 +10,14 @@ master:
   scheduler:
     bins:
       - "openshift start master controllers"
+      - "hyperkube kube-scheduler"
     confs:
       - /etc/origin/master/scheduler.json
 
   controllermanager:
     bins:
       - "openshift start master controllers"
+      - "hypershift openshift-controller-manager"
 
   etcd:
     bins:
diff --git a/cmd/common.go b/cmd/common.go
index a6a58bc..ec0601f 100644
--- a/cmd/common.go
+++ b/cmd/common.go
@@ -319,6 +319,7 @@ func getBenchmarkVersion(kubeVersion, benchmarkVersion string, v *viper.Viper) (
 
 // isMaster verify if master components are running on the node.
 func isMaster() bool {
+	loadConfig(check.MASTER)
 	return isThisNodeRunning(check.MASTER)
 }
 
diff --git a/cmd/common_test.go b/cmd/common_test.go
index f0dc131..7c95214 100644
--- a/cmd/common_test.go
+++ b/cmd/common_test.go
@@ -155,6 +155,20 @@ func TestIsMaster(t *testing.T) {
 			isMaster: false,
 		},
 	}
+	cfgDirOld := cfgDir
+	cfgDir = "../cfg"
+	defer func() {
+		cfgDir = cfgDirOld
+	}()
+
+	execCode := `#!/bin/sh
+	echo "Server Version: v1.13.10"
+	`
+	restore, err := fakeExecutableInPath("kubectl", execCode)
+	if err != nil {
+		t.Fatal("Failed when calling fakeExecutableInPath ", err)
+	}
+	defer restore()
 
 	for _, tc := range testCases {
 		cfgFile = tc.cfgFile
@@ -386,6 +400,73 @@ func TestValidTargets(t *testing.T) {
 	}
 }
 
+func TestIsEtcd(t *testing.T) {
+	testCases := []struct {
+		name            string
+		cfgFile         string
+		getBinariesFunc func(*viper.Viper, check.NodeType) (map[string]string, error)
+		isEtcd          bool
+	}{
+		{
+			name:    "valid config, is etcd and all components are running",
+			cfgFile: "../cfg/config.yaml",
+			getBinariesFunc: func(viper *viper.Viper, nt check.NodeType) (strings map[string]string, i error) {
+				return map[string]string{"etcd": "etcd"}, nil
+			},
+			isEtcd: true,
+		},
+		{
+			name:    "valid config, is etcd and but not all components are running",
+			cfgFile: "../cfg/config.yaml",
+			getBinariesFunc: func(viper *viper.Viper, nt check.NodeType) (strings map[string]string, i error) {
+				return map[string]string{}, nil
+			},
+			isEtcd: false,
+		},
+		{
+			name:    "valid config, is etcd, not all components are running and fails to find all binaries",
+			cfgFile: "../cfg/config.yaml",
+			getBinariesFunc: func(viper *viper.Viper, nt check.NodeType) (strings map[string]string, i error) {
+				return map[string]string{}, errors.New("failed to find binaries")
+			},
+			isEtcd: false,
+		},
+		{
+			name:    "valid config, does not include etcd",
+			cfgFile: "../cfg/node_only.yaml",
+			isEtcd:  false,
+		},
+	}
+	cfgDirOld := cfgDir
+	cfgDir = "../cfg"
+	defer func() {
+		cfgDir = cfgDirOld
+	}()
+
+	execCode := `#!/bin/sh
+	echo "Server Version: v1.15.03"
+	`
+	restore, err := fakeExecutableInPath("kubectl", execCode)
+	if err != nil {
+		t.Fatal("Failed when calling fakeExecutableInPath ", err)
+	}
+	defer restore()
+
+	for _, tc := range testCases {
+		cfgFile = tc.cfgFile
+		initConfig()
+
+		oldGetBinariesFunc := getBinariesFunc
+		getBinariesFunc = tc.getBinariesFunc
+		defer func() {
+			getBinariesFunc = oldGetBinariesFunc
+			cfgFile = ""
+		}()
+
+		assert.Equal(t, tc.isEtcd, isEtcd(), tc.name)
+	}
+}
+
 func loadConfigForTest() (*viper.Viper, error) {
 	viperWithData := viper.New()
 	viperWithData.SetConfigFile(filepath.Join("..", cfgDir, "config.yaml"))
@@ -410,11 +491,6 @@ func fakeExecutableInPath(execFile, execCode string) (restoreFn, error) {
 		return nil, err
 	}
 
-	err = os.Chdir(tmp)
-	if err != nil {
-		return nil, err
-	}
-
 	if len(execCode) > 0 {
 		ioutil.WriteFile(filepath.Join(tmp, execFile), []byte(execCode), 0700)
 	} else {
diff --git a/cmd/root.go b/cmd/root.go
index 6aeafde..55748ec 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -64,7 +64,7 @@ var RootCmd = &cobra.Command{
 	Run: func(cmd *cobra.Command, args []string) {
 		benchmarkVersion, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, viper.GetViper())
 		if err != nil {
-			exitWithError(err)
+			exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
 		}
 
 		if isMaster() {
@@ -81,7 +81,7 @@ var RootCmd = &cobra.Command{
 
 		// Etcd is only valid for CIS 1.5 and later,
 		// this a gatekeeper for previous versions.
-		if isEtcd() && validTargets(benchmarkVersion, []string{string(check.ETCD)}) {
+		if validTargets(benchmarkVersion, []string{string(check.ETCD)}) && isEtcd() {
 			glog.V(1).Info("== Running etcd checks ==\n")
 			runChecks(check.ETCD, loadConfig(check.ETCD))
 		}
-- 
GitLab