1
0
mirror of https://github.com/aquasecurity/kube-bench.git synced 2024-12-24 23:48:26 +00:00

Merge pull request #141 from aquasecurity/version-default

Default version
This commit is contained in:
Liz Rice 2018-07-02 15:36:31 +01:00 committed by GitHub
commit 668a9e10ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 117 additions and 28 deletions

View File

@ -17,6 +17,7 @@ package cmd
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"path/filepath" "path/filepath"
"github.com/aquasecurity/kube-bench/check" "github.com/aquasecurity/kube-bench/check"
@ -28,56 +29,50 @@ var (
errmsgs string errmsgs string
) )
func runChecks(t check.NodeType) { func runChecks(nodetype check.NodeType) {
var summary check.Summary var summary check.Summary
var nodetype string
var file string var file string
var err error var err error
var typeConf *viper.Viper var typeConf *viper.Viper
switch t { switch nodetype {
case check.MASTER: case check.MASTER:
file = masterFile file = masterFile
nodetype = "master"
case check.NODE: case check.NODE:
file = nodeFile file = nodeFile
nodetype = "node"
case check.FEDERATED: case check.FEDERATED:
file = federatedFile file = federatedFile
nodetype = "federated"
} }
var ver string path, err := getConfigFilePath(kubeVersion, getKubeVersion(), file)
if kubeVersion != "" { if err != nil {
ver = kubeVersion exitWithError(fmt.Errorf("can't find %s controls file in %s: %v", nodetype, cfgDir, err))
} else {
ver = getKubeVersion()
} }
switch ver {
case "1.9", "1.10":
continueWithError(nil, fmt.Sprintf("No CIS spec for %s - using tests from CIS 1.2.0 spec for Kubernetes 1.8\n", ver))
ver = "1.8"
}
path := filepath.Join(cfgDir, ver)
def := filepath.Join(path, file) def := filepath.Join(path, file)
in, err := ioutil.ReadFile(def) in, err := ioutil.ReadFile(def)
if err != nil { if err != nil {
exitWithError(fmt.Errorf("error opening %s controls file: %v", t, err)) exitWithError(fmt.Errorf("error opening %s controls file: %v", nodetype, err))
} }
glog.V(1).Info(fmt.Sprintf("Using benchmark file: %s\n", def))
// Merge kubernetes version specific config if any. // Merge kubernetes version specific config if any.
viper.SetConfigFile(path + "/config.yaml") viper.SetConfigFile(path + "/config.yaml")
err = viper.MergeInConfig() err = viper.MergeInConfig()
if err != nil { if err != nil {
continueWithError(err, fmt.Sprintf("Reading %s specific configuration file", ver)) if os.IsNotExist(err) {
glog.V(2).Info(fmt.Sprintf("No version-specific config.yaml file in %s", path))
} else {
exitWithError(fmt.Errorf("couldn't read config file %s: %v", path+"/config.yaml", err))
}
} else {
glog.V(1).Info(fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed()))
} }
typeConf = viper.Sub(nodetype)
// Get the set of exectuables and config files we care about on this type of node. This also // Get the set of exectuables and config files we care about on this type of node. This also
// checks that the executables we need for the node type are running. // checks that the executables we need for the node type are running.
typeConf = viper.Sub(string(nodetype))
binmap := getBinaries(typeConf) binmap := getBinaries(typeConf)
confmap := getConfigFiles(typeConf) confmap := getConfigFiles(typeConf)
@ -86,12 +81,9 @@ func runChecks(t check.NodeType) {
s = makeSubstitutions(s, "bin", binmap) s = makeSubstitutions(s, "bin", binmap)
s = makeSubstitutions(s, "conf", confmap) s = makeSubstitutions(s, "conf", confmap)
glog.V(1).Info(fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed())) controls, err := check.NewControls(nodetype, []byte(s))
glog.V(1).Info(fmt.Sprintf("Using benchmark file: %s\n", def))
controls, err := check.NewControls(t, []byte(s))
if err != nil { if err != nil {
exitWithError(fmt.Errorf("error setting up %s controls: %v", t, err)) exitWithError(fmt.Errorf("error setting up %s controls: %v", nodetype, err))
} }
if groupList != "" && checkList == "" { if groupList != "" && checkList == "" {

View File

@ -4,7 +4,9 @@ import (
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"regexp" "regexp"
"strconv"
"strings" "strings"
"github.com/aquasecurity/kube-bench/check" "github.com/aquasecurity/kube-bench/check"
@ -116,6 +118,57 @@ func getBinaries(v *viper.Viper) map[string]string {
return binmap return binmap
} }
// getConfigFilePath locates the config files we should be using based on either the specified
// version, or the running version of kubernetes if not specified
func getConfigFilePath(specifiedVersion string, runningVersion string, filename string) (path string, err error) {
var fileVersion string
if specifiedVersion != "" {
fileVersion = specifiedVersion
} else {
fileVersion = runningVersion
}
for {
path = filepath.Join(cfgDir, fileVersion)
file := filepath.Join(path, string(filename))
glog.V(2).Info(fmt.Sprintf("Looking for config file: %s\n", file))
if _, err = os.Stat(file); !os.IsNotExist(err) {
if specifiedVersion == "" && fileVersion != runningVersion {
glog.V(1).Info(fmt.Sprintf("No test file found for %s - using tests for Kubernetes %s\n", runningVersion, fileVersion))
}
return path, nil
}
// If we were given an explicit version to look for, don't look for any others
if specifiedVersion != "" {
return "", err
}
fileVersion = decrementVersion(fileVersion)
if fileVersion == "" {
return "", fmt.Errorf("no test files found <= runningVersion")
}
}
}
// decrementVersion decrements the version number
// We want to decrement individually even through versions where we don't supply test files
// just in case someone wants to specify their own test files for that version
func decrementVersion(version string) string {
split := strings.Split(version, ".")
minor, err := strconv.Atoi(split[1])
if err != nil {
return ""
}
if minor <= 1 {
return ""
}
split[1] = strconv.Itoa(minor - 1)
return strings.Join(split, ".")
}
// getConfigFiles finds which of the set of candidate config files exist // getConfigFiles finds which of the set of candidate config files exist
// accepts a string 't' which indicates the type of config file, conf, // accepts a string 't' which indicates the type of config file, conf,
// podspec or untifile. // podspec or untifile.
@ -275,7 +328,7 @@ func makeSubstitutions(s string, ext string, m map[string]string) string {
glog.V(2).Info(fmt.Sprintf("No subsitution for '%s'\n", subst)) glog.V(2).Info(fmt.Sprintf("No subsitution for '%s'\n", subst))
continue continue
} }
glog.V(1).Info(fmt.Sprintf("Substituting %s with '%s'\n", subst, v)) glog.V(2).Info(fmt.Sprintf("Substituting %s with '%s'\n", subst, v))
s = multiWordReplace(s, subst, v) s = multiWordReplace(s, subst, v)
} }

View File

@ -15,7 +15,9 @@
package cmd package cmd
import ( import (
"io/ioutil"
"os" "os"
"path/filepath"
"reflect" "reflect"
"strconv" "strconv"
"testing" "testing"
@ -306,3 +308,45 @@ func TestMakeSubsitutions(t *testing.T) {
}) })
} }
} }
func TestGetConfigFilePath(t *testing.T) {
var err error
cfgDir, err = ioutil.TempDir("", "kube-bench-test")
if err != nil {
t.Fatalf("Failed to create temp directory")
}
defer os.RemoveAll(cfgDir)
d := filepath.Join(cfgDir, "1.8")
err = os.Mkdir(d, 0666)
if err != nil {
t.Fatalf("Failed to create temp file")
}
ioutil.WriteFile(filepath.Join(d, "master.yaml"), []byte("hello world"), 0666)
cases := []struct {
specifiedVersion string
runningVersion string
succeed bool
exp string
}{
{runningVersion: "1.8", succeed: true, exp: d},
{runningVersion: "1.9", succeed: true, exp: d},
{runningVersion: "1.10", succeed: true, exp: d},
{runningVersion: "1.1", succeed: false},
{specifiedVersion: "1.8", succeed: true, exp: d},
{specifiedVersion: "1.9", succeed: false},
{specifiedVersion: "1.10", succeed: false},
}
for _, c := range cases {
t.Run(c.specifiedVersion+"-"+c.runningVersion, func(t *testing.T) {
path, err := getConfigFilePath(c.specifiedVersion, c.runningVersion, "/master.yaml")
if err != nil && c.succeed {
t.Fatalf("Error %v", err)
}
if path != c.exp {
t.Fatalf("Got %s expected %s", path, c.exp)
}
})
}
}