diff --git a/cfg/1.11/config.yaml b/cfg/1.11/config.yaml index 43a26e3..1d51f6c 100644 --- a/cfg/1.11/config.yaml +++ b/cfg/1.11/config.yaml @@ -9,39 +9,21 @@ 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 - - /etc/kubernetes/kubelet.conf - defaultconf: /etc/systemd/system/kubelet.service.d/10-kubeadm.conf + defaultconf: /etc/kubernetes/kubelet.conf + defaultsvc: /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.11/node.yaml b/cfg/1.11/node.yaml index 1a61899..18e4876 100644 --- a/cfg/1.11/node.yaml +++ b/cfg/1.11/node.yaml @@ -362,7 +362,7 @@ groups: - id: 2.2.3 text: "Ensure that the kubelet service 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 $kubeletsvc; then stat -c %a $kubeletsvc; fi'" tests: bin_op: or test_items: @@ -384,12 +384,12 @@ groups: remediation: | Run the below command (based on the file location on your system) on the each worker node. For example, - chmod 755 $kubeletconf + chmod 755 $kubeletsvc scored: true - id: 2.2.4 text: "Ensure that the kubelet service 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 $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'" tests: test_items: - flag: "root:root" @@ -397,7 +397,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 $kubeletsvc scored: true - id: 2.2.5 diff --git a/cmd/common.go b/cmd/common.go index 54b8b33..2596114 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -79,11 +79,13 @@ func runChecks(nodetype check.NodeType) { typeConf = viper.Sub(string(nodetype)) binmap := getBinaries(typeConf) confmap := getConfigFiles(typeConf) + svcmap := getServiceFiles(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) controls, err := check.NewControls(nodetype, []byte(s)) if err != nil { diff --git a/cmd/util.go b/cmd/util.go index 4c62841..24d6d9d 100644 --- a/cmd/util.go +++ b/cmd/util.go @@ -172,8 +172,6 @@ func decrementVersion(version string) string { } // getConfigFiles finds which of the set of candidate config files exist -// accepts a string 't' which indicates the type of config file, conf, -// podspec or untifile. func getConfigFiles(v *viper.Viper) map[string]string { confmap := make(map[string]string) @@ -204,6 +202,37 @@ func getConfigFiles(v *viper.Viper) map[string]string { return confmap } +// getServiceFiles finds which of the set of candidate service files exist +func getServiceFiles(v *viper.Viper) map[string]string { + svcmap := 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 + svc := findConfigFile(s.GetStringSlice("svc")) + if svc == "" { + if s.IsSet("defaultsvc") { + svc = s.GetString("defaultsvc") + glog.V(2).Info(fmt.Sprintf("Using default service file name '%s' for component %s", svc, 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)) + svc = component + } + } else { + glog.V(2).Info(fmt.Sprintf("Component %s uses service file '%s'", component, svc)) + } + + svcmap[component] = svc + } + + return svcmap +} + // verifyBin checks that the binary specified is running func verifyBin(bin string) bool { diff --git a/cmd/util_test.go b/cmd/util_test.go index 539f400..cf8cb0d 100644 --- a/cmd/util_test.go +++ b/cmd/util_test.go @@ -289,6 +289,81 @@ func TestGetConfigFiles(t *testing.T) { } } +func TestGetServiceFiles(t *testing.T) { + cases := []struct { + config map[string]interface{} + exp map[string]string + statResults []error + }{ + { + config: map[string]interface{}{ + "components": []string{"kubelet"}, + "kubelet": map[string]interface{}{"svc": []string{"kubelet", "10-kubeadm.conf"}}, + }, + statResults: []error{os.ErrNotExist, nil}, + exp: map[string]string{"kubelet": "10-kubeadm.conf"}, + }, + { + // Component "thing" isn't included in the list of components + config: map[string]interface{}{ + "components": []string{"kubelet"}, + "kubelet": map[string]interface{}{"svc": []string{"kubelet", "10-kubeadm.conf"}}, + "thing": map[string]interface{}{"svc": []string{"/my/file/thing"}}, + }, + statResults: []error{os.ErrNotExist, nil}, + exp: map[string]string{"kubelet": "10-kubeadm.conf"}, + }, + { + // More than one component + config: map[string]interface{}{ + "components": []string{"kubelet", "thing"}, + "kubelet": map[string]interface{}{"svc": []string{"kubelet", "10-kubeadm.conf"}}, + "thing": map[string]interface{}{"svc": []string{"/my/file/thing"}}, + }, + statResults: []error{os.ErrNotExist, nil, nil}, + exp: map[string]string{"kubelet": "10-kubeadm.conf", "thing": "/my/file/thing"}, + }, + { + // Default thing to specified default service + config: map[string]interface{}{ + "components": []string{"kubelet", "thing"}, + "kubelet": map[string]interface{}{"svc": []string{"kubelet", "10-kubeadm.conf"}}, + "thing": map[string]interface{}{"svc": []string{"/my/file/thing"}, "defaultsvc": "another/thing"}, + }, + statResults: []error{os.ErrNotExist, nil, os.ErrNotExist}, + exp: map[string]string{"kubelet": "10-kubeadm.conf", "thing": "another/thing"}, + }, + { + // Default thing to component name + config: map[string]interface{}{ + "components": []string{"kubelet", "thing"}, + "kubelet": map[string]interface{}{"svc": []string{"kubelet", "10-kubeadm.conf"}}, + "thing": map[string]interface{}{"svc": []string{"/my/file/thing"}}, + }, + statResults: []error{os.ErrNotExist, nil, os.ErrNotExist}, + exp: map[string]string{"kubelet": "10-kubeadm.conf", "thing": "thing"}, + }, + } + + v := viper.New() + statFunc = fakestat + + for id, c := range cases { + t.Run(strconv.Itoa(id), func(t *testing.T) { + for k, val := range c.config { + v.Set(k, val) + } + e = c.statResults + eIndex = 0 + + m := getServiceFiles(v) + if !reflect.DeepEqual(m, c.exp) { + t.Fatalf("Got %v\nExpected %v", m, c.exp) + } + }) + } +} + func TestMakeSubsitutions(t *testing.T) { cases := []struct { input string