From ed218394648e6d4d57132defc88b38b24262ad33 Mon Sep 17 00:00:00 2001 From: Abubakr-Sadik Nii Nai Davis Date: Tue, 23 Oct 2018 02:26:38 +0000 Subject: [PATCH] Add getServiceFiles function. The CIS benchmark check for node checks 2 config files for kubelet: - kubelet config file (kubelet.conf) - kubelet systemd unitfile (10-kubeadm.conf) The getServiceFiles function gets candidates for kubelet systemd unitfile and returns valid untifiles. --- cmd/common.go | 2 ++ cmd/util.go | 33 +++++++++++++++++++-- cmd/util_test.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) 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