Compare commits

...

19 Commits

Author SHA1 Message Date
Liz Rice
b1e41d345f Merge pull request #147 from aquasecurity/version-fix
Shouldn't need kubelet or kubectl if version specified
2018-07-28 14:53:56 +01:00
Liz Rice
ccc2b6c9ae Shouldn't need kubelet or kubectl if version specified 2018-07-26 12:03:09 +01:00
Liz Rice
668a9e10ce Merge pull request #141 from aquasecurity/version-default
Default version
2018-07-02 15:36:31 +01:00
Liz Rice
8c3bb62dd4 Merge pull request #140 from aquasecurity/manifest-extension
Inlcude .manifest extension config files for kops & kubespray
2018-07-02 15:34:49 +01:00
Liz Rice
9d0141871a Use new utility function for finding correct config files.
Improve order of message output
Remove unnecessary local variable
2018-06-29 12:20:29 +01:00
Liz Rice
344d2bfd24 Utility for getting the right config file for the Kubernetes version 2018-06-29 12:19:34 +01:00
Liz Rice
ecd14ed682 File substitutions should be a detailed log 2018-06-29 12:19:00 +01:00
Liz Rice
223ac14642 Don't override version specified on command line 2018-06-29 10:35:44 +01:00
Liz Rice
c44e0db97b Inlcude .manifest extension config files for kops & kubespray 2018-06-29 10:24:09 +01:00
Liz Rice
0bc004468b Include .manifest extensions as an option for config files (as used by kops and kubespreay) 2018-06-29 10:23:06 +01:00
Liz Rice
83704a7d89 Merge pull request #134 from hutr/master
fix grep string for check 1.4.11 and 1.4.12
2018-06-18 08:44:13 -07:00
Liz Rice
024b7ed396 Merge branch 'master' into master 2018-06-18 08:30:24 -07:00
Liz Rice
c5e04677cf Merge pull request #138 from jgsqware/patch-1
Rule node 2.2.4 is not correct
2018-06-18 08:28:38 -07:00
Julien Garcia Gonzalez
2073e08363 update 2.2.4 rules 2018-06-18 13:44:25 +02:00
Julien Garcia Gonzalez
db096c9f51 Rule node 2.2.4 is not correct 2018-06-15 15:49:55 +02:00
hutr
d736d10f90 fix sed string for 1.4.12 2018-06-07 16:34:03 +02:00
hutr
50a3725ff2 Merge branch 'master' into master 2018-06-07 16:12:04 +02:00
hutr
468f5fac6e changes for 1.4.11 and 1.4.2
added tests: for 1.4.11 and removed grep -v grep for both
2018-06-07 16:08:43 +02:00
hutr
e4100a4435 fixed grep string for 1.4.11 and 1.4.22
check 1.4.11 and 1.4.22 FAIL even when permissions is correct.
2018-05-28 15:39:07 +02:00
6 changed files with 136 additions and 36 deletions

View File

@@ -9,21 +9,27 @@
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:

View File

@@ -942,7 +942,7 @@ groups:
- id: 1.4.11
text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Scored)"
audit: ps -ef | grep $etcdbin | grep -v grep | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %a
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %a
tests:
test_items:
- flag: "700"
@@ -960,7 +960,7 @@ groups:
- id: 1.4.12
text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)"
audit: ps -ef | grep $etcdbin | grep -v grep | sed 's%.*data-dir[= ]\(\S*\)%\1%' | xargs stat -c %U:%G
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %U:%G
tests:
test_items:
- flag: "etcd:etcd"

View File

@@ -368,8 +368,7 @@ groups:
scored: true
- id: 2.2.4
text: "Ensure that the kubelet service file permissions are set to 644 or
more restrictive (Scored)"
text: "2.2.4 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'"
tests:
test_items:

View File

@@ -17,6 +17,7 @@ package cmd
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/aquasecurity/kube-bench/check"
@@ -28,56 +29,54 @@ var (
errmsgs string
)
func runChecks(t check.NodeType) {
func runChecks(nodetype check.NodeType) {
var summary check.Summary
var nodetype string
var file string
var err error
var typeConf *viper.Viper
switch t {
switch nodetype {
case check.MASTER:
file = masterFile
nodetype = "master"
case check.NODE:
file = nodeFile
nodetype = "node"
case check.FEDERATED:
file = federatedFile
nodetype = "federated"
}
var ver string
if kubeVersion != "" {
ver = kubeVersion
} else {
ver = getKubeVersion()
runningVersion, err := getKubeVersion()
if err != nil && kubeVersion == "" {
exitWithError(fmt.Errorf("Version check failed: %s\nAlternatively, you can specify the version with --version", err))
}
path, err := getConfigFilePath(kubeVersion, runningVersion, file)
if err != nil {
exitWithError(fmt.Errorf("can't find %s controls file in %s: %v", nodetype, cfgDir, err))
}
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)
in, err := ioutil.ReadFile(def)
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.
viper.SetConfigFile(path + "/config.yaml")
err = viper.MergeInConfig()
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
// checks that the executables we need for the node type are running.
typeConf = viper.Sub(string(nodetype))
binmap := getBinaries(typeConf)
confmap := getConfigFiles(typeConf)
@@ -86,12 +85,9 @@ func runChecks(t check.NodeType) {
s = makeSubstitutions(s, "bin", binmap)
s = makeSubstitutions(s, "conf", confmap)
glog.V(1).Info(fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed()))
glog.V(1).Info(fmt.Sprintf("Using benchmark file: %s\n", def))
controls, err := check.NewControls(t, []byte(s))
controls, err := check.NewControls(nodetype, []byte(s))
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 == "" {

View File

@@ -4,7 +4,9 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/aquasecurity/kube-bench/check"
@@ -116,6 +118,59 @@ func getBinaries(v *viper.Viper) map[string]string {
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
}
glog.V(2).Info(fmt.Sprintf("Looking for config for version %s", fileVersion))
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
// accepts a string 't' which indicates the type of config file, conf,
// podspec or untifile.
@@ -212,19 +267,19 @@ func multiWordReplace(s string, subname string, sub string) string {
return strings.Replace(s, subname, sub, -1)
}
func getKubeVersion() string {
func getKubeVersion() (string, error) {
// These executables might not be on the user's path.
_, err := exec.LookPath("kubectl")
if err != nil {
_, err = exec.LookPath("kubelet")
if err != nil {
exitWithError(fmt.Errorf("Version check failed: need kubectl or kubelet binaries to get kubernetes version.\nAlternately, you can specify the version with --version"))
return "", fmt.Errorf("need kubectl or kubelet binaries to get kubernetes version")
}
return getKubeVersionFromKubelet()
return getKubeVersionFromKubelet(), nil
}
return getKubeVersionFromKubectl()
return getKubeVersionFromKubectl(), nil
}
func getKubeVersionFromKubectl() string {
@@ -275,7 +330,7 @@ func makeSubstitutions(s string, ext string, m map[string]string) string {
glog.V(2).Info(fmt.Sprintf("No subsitution for '%s'\n", subst))
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)
}

View File

@@ -15,7 +15,9 @@
package cmd
import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strconv"
"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)
}
})
}
}