From a88b0703d86e7b26752c7cd4695704b08d7c5f60 Mon Sep 17 00:00:00 2001 From: Abubakr-Sadik Nii Nai Davis Date: Wed, 27 Feb 2019 22:08:57 +0000 Subject: [PATCH] Add kubeconfig variable substitution for kubelet and proxy. There are checks for the kubeconfig for both kubelet and proxy which the current kube-bench implementation does not check for properly. kube-bench checks the wrong files. This PR adds support for variable substitution for all the config file types are that should be checked in the CIS benchmarks. This PR also fixes a buggy in CIS 1.3.0 check 2.2.9, which checks for ownership of the kubelet config file /var/lib/kubelet/config.yaml but recommends changing ownership of kubelet kubeconfig file /etc/kubernetes/kubelet.conf as remediation. --- cfg/1.11/node.yaml | 24 ++++++++++++------------ cfg/1.8/config.yaml | 23 ----------------------- cfg/1.8/node.yaml | 16 ++++++++-------- cfg/config.yaml | 8 +++----- cmd/common.go | 2 ++ cmd/util.go | 31 +++++++++++++++++++++++++++++++ 6 files changed, 56 insertions(+), 48 deletions(-) diff --git a/cfg/1.11/node.yaml b/cfg/1.11/node.yaml index 7b808ba..82a4d7c 100644 --- a/cfg/1.11/node.yaml +++ b/cfg/1.11/node.yaml @@ -320,7 +320,7 @@ groups: - id: 2.2.1 text: "Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletconf; then stat -c %a $kubeletconf; fi'" + audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; fi'" tests: bin_op: or test_items: @@ -342,12 +342,12 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chmod 644 $kubeletconf + chmod 644 $kubeletkubeconfig scored: true - id: 2.2.2 text: "Ensure that the kubelet.conf file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletconf; then stat -c %U:%G $kubeletconf; fi'" + audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; fi'" tests: test_items: - flag: "root:root" @@ -358,7 +358,7 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chown root:root $kubeletconf + chown root:root $kubeletkubeconfig scored: true - id: 2.2.3 @@ -404,7 +404,7 @@ groups: - id: 2.2.5 text: "Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $proxyconf; then stat -c %a $proxyconf; fi'" + audit: "/bin/sh -c 'if test -e $proxykubeconfig; then stat -c %a $proxykubeconfig; fi'" tests: bin_op: or test_items: @@ -426,12 +426,12 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chmod 644 $proxyconf + chmod 644 $proxykubeconfig scored: true - id: 2.2.6 text: "Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $proxyconf; then stat -c %U:%G $proxyconf; fi'" + audit: "/bin/sh -c 'if test -e $proxykubeconfig; then stat -c %U:%G $proxykubeconfig; fi'" tests: test_items: - flag: "root:root" @@ -439,7 +439,7 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chown root:root $proxyconf + chown root:root $proxykubeconfig scored: true - id: 2.2.7 @@ -462,19 +462,19 @@ groups: - id: 2.2.9 text: "Ensure that the kubelet configuration file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e /var/lib/kubelet/config.yaml; then stat -c %U:%G /var/lib/kubelet/config.yaml; fi'" + audit: "/bin/sh -c 'if test -e $kubeletconf; then stat -c %U:%G $kubeletconf; fi'" tests: test_items: - flag: "root:root" set: true remediation: | Run the following command (using the config file location identied in the Audit step) - chown root:root /etc/kubernetes/kubelet.conf + chown root:root $kubeletconf scored: true - id: 2.2.10 text: "Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e /var/lib/kubelet/config.yaml; then stat -c %a /var/lib/kubelet/config.yaml; fi'" + audit: "/bin/sh -c 'if test -e $kubeletconf; then stat -c %a $kubeletconf; fi'" tests: bin_op: or test_items: @@ -495,5 +495,5 @@ groups: set: true remediation: | Run the following command (using the config file location identied in the Audit step) - chmod 644 /var/lib/kubelet/config.yaml + chmod 644 $kubeletconf scored: true diff --git a/cfg/1.8/config.yaml b/cfg/1.8/config.yaml index 1fec47e..3caaa5d 100644 --- a/cfg/1.8/config.yaml +++ b/cfg/1.8/config.yaml @@ -9,36 +9,13 @@ master: apiserver: - confs: - - /etc/kubernetes/manifests/kube-apiserver.yaml - - /etc/kubernetes/manifests/kube-apiserver.manifest defaultconf: /etc/kubernetes/manifests/kube-apiserver.yaml scheduler: - confs: - - /etc/kubernetes/manifests/kube-scheduler.yaml - - /etc/kubernetes/manifests/kube-scheduler.manifest defaultconf: /etc/kubernetes/manifests/kube-scheduler.yaml controllermanager: - confs: - - /etc/kubernetes/manifests/kube-controller-manager.yaml - - /etc/kubernetes/manifests/kube-controller-manager.manifest defaultconf: /etc/kubernetes/manifests/kube-controller-manager.yaml etcd: - confs: - - /etc/kubernetes/manifests/etcd.yaml - - /etc/kubernetes/manifests/etcd.manifest defaultconf: /etc/kubernetes/manifests/etcd.yaml - -node: - kubelet: - confs: - - /etc/systemd/system/kubelet.service.d/10-kubeadm.conf - defaultconf: /etc/systemd/system/kubelet.service.d/10-kubeadm.conf - - proxy: - confs: - - /etc/kubernetes/addons/kube-proxy-daemonset.yaml - defaultconf: /etc/kubernetes/addons/kube-proxy-daemonset.yaml diff --git a/cfg/1.8/node.yaml b/cfg/1.8/node.yaml index db47007..014ced4 100644 --- a/cfg/1.8/node.yaml +++ b/cfg/1.8/node.yaml @@ -297,7 +297,7 @@ groups: - id: 2.2.1 text: "Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletconf; then stat -c %a $kubeletconf; fi'" + audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; fi'" tests: bin_op: or test_items: @@ -319,12 +319,12 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chmod 644 $kubeletconf + chmod 644 $kubeletkubeconfig scored: true - id: 2.2.2 text: "Ensure that the kubelet.conf file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletconf; then stat -c %U:%G $kubeletconf; fi'" + audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; fi'" tests: test_items: - flag: "root:root" @@ -335,7 +335,7 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chown root:root $kubeletconf + chown root:root $kubeletkubeconfig scored: true - id: 2.2.3 @@ -382,7 +382,7 @@ groups: - id: 2.2.5 text: "Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $proxyconf; then stat -c %a $proxyconf; fi'" + audit: "/bin/sh -c 'if test -e $proxykubeconfig; then stat -c %a $proxykubeconfig; fi'" tests: bin_op: or test_items: @@ -404,12 +404,12 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chmod 644 $proxyconf + chmod 644 $proxykubeconfig scored: true - id: 2.2.6 text: "Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $proxyconf; then stat -c %U:%G $proxyconf; fi'" + audit: "/bin/sh -c 'if test -e $proxykubeconfig; then stat -c %U:%G $proxykubeconfig; fi'" tests: test_items: - flag: "root:root" @@ -417,7 +417,7 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chown root:root $proxyconf + chown root:root $proxykubeconfig scored: true - id: 2.2.7 diff --git a/cfg/config.yaml b/cfg/config.yaml index 563bb5e..82ed1a1 100644 --- a/cfg/config.yaml +++ b/cfg/config.yaml @@ -78,11 +78,9 @@ node: bins: - "hyperkube kubelet" - "kubelet" - confs: - - /etc/kubernetes/kubelet.conf - - /etc/kubernetes/kubelet - defaultconf: "/etc/kubernetes/kubelet.conf" + defaultconf: "/var/lib/kubelet/config.yaml" defaultsvc: "/etc/systemd/system/kubelet.service.d/10-kubeadm.conf" + defaultkubeconfig: "/etc/kubernetes/kubelet.conf" proxy: bins: @@ -90,9 +88,9 @@ node: - "hyperkube proxy" - "proxy" confs: - - /etc/kubernetes/proxy.conf - /etc/kubernetes/proxy - /etc/kubernetes/addons/kube-proxy-daemonset.yaml + defaultkubeconfig: "/etc/kubernetes/proxy.conf" federated: components: diff --git a/cmd/common.go b/cmd/common.go index 2cfa310..b4d46c2 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -83,12 +83,14 @@ func runChecks(nodetype check.NodeType) { binmap := getBinaries(typeConf) confmap := getConfigFiles(typeConf) svcmap := getServiceFiles(typeConf) + kubeconfmap := getKubeConfigFiles(typeConf) // Variable substitutions. Replace all occurrences of variables in controls files. s := string(in) s = makeSubstitutions(s, "bin", binmap) s = makeSubstitutions(s, "conf", confmap) s = makeSubstitutions(s, "svc", svcmap) + s = makeSubstitutions(s, "kubeconfig", kubeconfmap) controls, err := check.NewControls(nodetype, []byte(s)) if err != nil { diff --git a/cmd/util.go b/cmd/util.go index 97cd94a..c3ae950 100644 --- a/cmd/util.go +++ b/cmd/util.go @@ -219,6 +219,37 @@ func getServiceFiles(v *viper.Viper) map[string]string { return svcmap } +// getKubeConfigFiles finds which of the set of candidate kubeconfig files exist +func getKubeConfigFiles(v *viper.Viper) map[string]string { + kubeconfigmap := make(map[string]string) + + for _, component := range v.GetStringSlice("components") { + s := v.Sub(component) + if s == nil { + continue + } + + // See if any of the candidate config files exist + kubeconfig := findConfigFile(s.GetStringSlice("kubeconfig")) + if kubeconfig == "" { + if s.IsSet("defaultkubeconfig") { + kubeconfig = s.GetString("defaultkubeconfig") + glog.V(2).Info(fmt.Sprintf("Using default kubeconfig file name '%s' for component %s", kubeconfig, component)) + } else { + // Default the service file name that we'll substitute to the name of the component + glog.V(2).Info(fmt.Sprintf("Missing service file for %s", component)) + kubeconfig = component + } + } else { + glog.V(2).Info(fmt.Sprintf("Component %s uses service file '%s'", component, kubeconfig)) + } + + kubeconfigmap[component] = kubeconfig + } + + return kubeconfigmap +} + // verifyBin checks that the binary specified is running func verifyBin(bin string) bool {