mirror of
https://github.com/aquasecurity/kube-bench.git
synced 2024-11-21 23:58:06 +00:00
Update auto-detection codes to support check platform version (#1074)
Co-authored-by: Yoav Rotem <yoavrotems97@gmail.com>
This commit is contained in:
parent
7dd6fccd17
commit
1fad8f5083
@ -313,13 +313,13 @@ func loadTargetMapping(v *viper.Viper) (map[string][]string, error) {
|
||||
return benchmarkVersionToTargetsMap, nil
|
||||
}
|
||||
|
||||
func getBenchmarkVersion(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper) (bv string, err error) {
|
||||
func getBenchmarkVersion(kubeVersion, benchmarkVersion string, platform Platform, v *viper.Viper) (bv string, err error) {
|
||||
detecetedKubeVersion = "none"
|
||||
if !isEmpty(kubeVersion) && !isEmpty(benchmarkVersion) {
|
||||
return "", fmt.Errorf("It is an error to specify both --version and --benchmark flags")
|
||||
}
|
||||
if isEmpty(benchmarkVersion) && isEmpty(kubeVersion) && !isEmpty(platformName) {
|
||||
benchmarkVersion = getPlatformBenchmarkVersion(platformName)
|
||||
if isEmpty(benchmarkVersion) && isEmpty(kubeVersion) && !isEmpty(platform.Name) {
|
||||
benchmarkVersion = getPlatformBenchmarkVersion(platform)
|
||||
if !isEmpty(benchmarkVersion) {
|
||||
detecetedKubeVersion = benchmarkVersion
|
||||
}
|
||||
|
@ -324,9 +324,9 @@ func TestGetBenchmarkVersion(t *testing.T) {
|
||||
t.Fatalf("Unable to load config file %v", err)
|
||||
}
|
||||
|
||||
type getBenchmarkVersionFnToTest func(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper) (string, error)
|
||||
type getBenchmarkVersionFnToTest func(kubeVersion, benchmarkVersion string, platform Platform, v *viper.Viper) (string, error)
|
||||
|
||||
withFakeKubectl := func(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
|
||||
withFakeKubectl := func(kubeVersion, benchmarkVersion string, platform Platform, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
|
||||
execCode := `#!/bin/sh
|
||||
echo '{"serverVersion": {"major": "1", "minor": "18", "gitVersion": "v1.18.10"}}'
|
||||
`
|
||||
@ -336,40 +336,40 @@ func TestGetBenchmarkVersion(t *testing.T) {
|
||||
}
|
||||
defer restore()
|
||||
|
||||
return fn(kubeVersion, benchmarkVersion, platformName, v)
|
||||
return fn(kubeVersion, benchmarkVersion, platform, v)
|
||||
}
|
||||
|
||||
withNoPath := func(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
|
||||
withNoPath := func(kubeVersion, benchmarkVersion string, platform Platform, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
|
||||
restore, err := prunePath()
|
||||
if err != nil {
|
||||
t.Fatal("Failed when calling prunePath ", err)
|
||||
}
|
||||
defer restore()
|
||||
|
||||
return fn(kubeVersion, benchmarkVersion, platformName, v)
|
||||
return fn(kubeVersion, benchmarkVersion, platform, v)
|
||||
}
|
||||
|
||||
type getBenchmarkVersionFn func(string, string, string, *viper.Viper, getBenchmarkVersionFnToTest) (string, error)
|
||||
type getBenchmarkVersionFn func(string, string, Platform, *viper.Viper, getBenchmarkVersionFnToTest) (string, error)
|
||||
cases := []struct {
|
||||
n string
|
||||
kubeVersion string
|
||||
benchmarkVersion string
|
||||
platformName string
|
||||
platform Platform
|
||||
v *viper.Viper
|
||||
callFn getBenchmarkVersionFn
|
||||
exp string
|
||||
succeed bool
|
||||
}{
|
||||
{n: "both versions", kubeVersion: "1.11", benchmarkVersion: "cis-1.3", platformName: "", exp: "cis-1.3", callFn: withNoPath, v: viper.New(), succeed: false},
|
||||
{n: "no version-missing-kubectl", kubeVersion: "", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "cis-1.6", callFn: withNoPath, succeed: true},
|
||||
{n: "no version-fakeKubectl", kubeVersion: "", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "cis-1.6", callFn: withFakeKubectl, succeed: true},
|
||||
{n: "kubeVersion", kubeVersion: "1.15", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "cis-1.5", callFn: withNoPath, succeed: true},
|
||||
{n: "ocpVersion310", kubeVersion: "ocp-3.10", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
|
||||
{n: "ocpVersion311", kubeVersion: "ocp-3.11", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
|
||||
{n: "gke12", kubeVersion: "gke-1.2.0", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "gke-1.2.0", callFn: withNoPath, succeed: true},
|
||||
{n: "both versions", kubeVersion: "1.11", benchmarkVersion: "cis-1.3", platform: Platform{}, exp: "cis-1.3", callFn: withNoPath, v: viper.New(), succeed: false},
|
||||
{n: "no version-missing-kubectl", kubeVersion: "", benchmarkVersion: "", platform: Platform{}, v: viperWithData, exp: "cis-1.6", callFn: withNoPath, succeed: true},
|
||||
{n: "no version-fakeKubectl", kubeVersion: "", benchmarkVersion: "", platform: Platform{}, v: viperWithData, exp: "cis-1.6", callFn: withFakeKubectl, succeed: true},
|
||||
{n: "kubeVersion", kubeVersion: "1.15", benchmarkVersion: "", platform: Platform{}, v: viperWithData, exp: "cis-1.5", callFn: withNoPath, succeed: true},
|
||||
{n: "ocpVersion310", kubeVersion: "ocp-3.10", benchmarkVersion: "", platform: Platform{}, v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
|
||||
{n: "ocpVersion311", kubeVersion: "ocp-3.11", benchmarkVersion: "", platform: Platform{}, v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
|
||||
{n: "gke12", kubeVersion: "gke-1.2.0", benchmarkVersion: "", platform: Platform{}, v: viperWithData, exp: "gke-1.2.0", callFn: withNoPath, succeed: true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
rv, err := c.callFn(c.kubeVersion, c.benchmarkVersion, c.platformName, c.v, getBenchmarkVersion)
|
||||
rv, err := c.callFn(c.kubeVersion, c.benchmarkVersion, c.platform, c.v, getBenchmarkVersion)
|
||||
if c.succeed {
|
||||
if err != nil {
|
||||
t.Errorf("[%q]-Unexpected error: %v", c.n, err)
|
||||
|
@ -28,7 +28,7 @@ var masterCmd = &cobra.Command{
|
||||
Short: "Run Kubernetes benchmark checks from the master.yaml file.",
|
||||
Long: `Run Kubernetes benchmark checks from the master.yaml file in cfg/<version>.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformInfo(), viper.GetViper())
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ var nodeCmd = &cobra.Command{
|
||||
Short: "Run Kubernetes benchmark checks from the node.yaml file.",
|
||||
Long: `Run Kubernetes benchmark checks from the node.yaml file in cfg/<version>.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformInfo(), viper.GetViper())
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ var RootCmd = &cobra.Command{
|
||||
Short: "Run CIS Benchmarks checks against a Kubernetes deployment",
|
||||
Long: `This tool runs the CIS Kubernetes Benchmark (https://www.cisecurity.org/benchmark/kubernetes/)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformInfo(), viper.GetViper())
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ var runCmd = &cobra.Command{
|
||||
exitWithError(fmt.Errorf("unable to get `targets` from command line :%v", err))
|
||||
}
|
||||
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
|
||||
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformInfo(), viper.GetViper())
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("unable to get benchmark version. error: %v", err))
|
||||
}
|
||||
|
65
cmd/util.go
65
cmd/util.go
@ -42,6 +42,15 @@ func init() {
|
||||
getBinariesFunc = getBinaries
|
||||
}
|
||||
|
||||
type Platform struct {
|
||||
Name string
|
||||
Version string
|
||||
}
|
||||
|
||||
func (p Platform) String() string {
|
||||
return fmt.Sprintf("Platform{ Name: %s Version: %s }", p.Name, p.Version)
|
||||
}
|
||||
|
||||
func exitWithError(err error) {
|
||||
fmt.Fprintf(os.Stderr, "\n%v\n", err)
|
||||
// flush before exit non-zero
|
||||
@ -427,49 +436,59 @@ These program names are provided in the config.yaml, section '%s.%s.bins'
|
||||
return fmt.Sprintf(errMessageTemplate, component, componentRoleName, binList, componentType, component)
|
||||
}
|
||||
|
||||
func getPlatformName() string {
|
||||
func getPlatformInfo() Platform {
|
||||
|
||||
openShiftVersion := getOpenShiftVersion()
|
||||
if openShiftVersion != "" {
|
||||
return openShiftVersion
|
||||
openShiftInfo := getOpenShiftInfo()
|
||||
if openShiftInfo.Name != "" && openShiftInfo.Version != "" {
|
||||
return openShiftInfo
|
||||
}
|
||||
|
||||
kv, err := getKubeVersion()
|
||||
if err != nil {
|
||||
glog.V(2).Info(err)
|
||||
return ""
|
||||
return Platform{}
|
||||
}
|
||||
return getPlatformNameFromVersion(kv.GitVersion)
|
||||
return getPlatformInfoFromVersion(kv.GitVersion)
|
||||
}
|
||||
|
||||
func getPlatformNameFromVersion(s string) string {
|
||||
versionRe := regexp.MustCompile(`v\d+\.\d+\.\d+-(\w+)(?:[.\-])\w+`)
|
||||
func getPlatformInfoFromVersion(s string) Platform {
|
||||
versionRe := regexp.MustCompile(`v(\d+\.\d+)\.\d+-(\w+)(?:[.\-])\w+`)
|
||||
subs := versionRe.FindStringSubmatch(s)
|
||||
if len(subs) < 2 {
|
||||
return ""
|
||||
if len(subs) < 3 {
|
||||
return Platform{}
|
||||
}
|
||||
return Platform{
|
||||
Name: subs[2],
|
||||
Version: subs[1],
|
||||
}
|
||||
return subs[1]
|
||||
}
|
||||
|
||||
func getPlatformBenchmarkVersion(platform string) string {
|
||||
func getPlatformBenchmarkVersion(platform Platform) string {
|
||||
glog.V(3).Infof("getPlatformBenchmarkVersion platform: %s", platform)
|
||||
switch platform {
|
||||
switch platform.Name {
|
||||
case "eks":
|
||||
return "eks-1.0.1"
|
||||
case "gke":
|
||||
// TODO: support check kubeVersion
|
||||
return "gke-1.2.0"
|
||||
switch platform.Version {
|
||||
case "1.15", "1.16", "1.17", "1.18", "1.19":
|
||||
return "gke-1.0"
|
||||
default:
|
||||
return "gke-1.2.0"
|
||||
}
|
||||
case "aliyun":
|
||||
return "ack-1.0"
|
||||
case "ocp-3.10":
|
||||
return "rh-0.7"
|
||||
case "ocp-4.1":
|
||||
return "rh-1.0"
|
||||
case "ocp":
|
||||
switch platform.Version {
|
||||
case "3.10":
|
||||
return "rh-0.7"
|
||||
case "4.1":
|
||||
return "rh-1.0"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getOpenShiftVersion() string {
|
||||
func getOpenShiftInfo() Platform {
|
||||
glog.V(1).Info("Checking for oc")
|
||||
_, err := exec.LookPath("oc")
|
||||
|
||||
@ -485,10 +504,10 @@ func getOpenShiftVersion() string {
|
||||
subs = versionRe.FindStringSubmatch(string(out))
|
||||
}
|
||||
if len(subs) > 1 {
|
||||
glog.V(2).Infof("OCP output '%s' \nplatform is %s \nocp %v", string(out), getPlatformNameFromVersion(string(out)), subs[1])
|
||||
glog.V(2).Infof("OCP output '%s' \nplatform is %s \nocp %v", string(out), getPlatformInfoFromVersion(string(out)), subs[1])
|
||||
ocpBenchmarkVersion, err := getOcpValidVersion(subs[1])
|
||||
if err == nil {
|
||||
return fmt.Sprintf("ocp-%s", ocpBenchmarkVersion)
|
||||
return Platform{Name: "ocp", Version: ocpBenchmarkVersion}
|
||||
} else {
|
||||
glog.V(1).Infof("Can't get getOcpValidVersion: %v", err)
|
||||
}
|
||||
@ -501,7 +520,7 @@ func getOpenShiftVersion() string {
|
||||
} else {
|
||||
glog.V(1).Infof("Can't find oc command: %v", err)
|
||||
}
|
||||
return ""
|
||||
return Platform{}
|
||||
}
|
||||
|
||||
func getOcpValidVersion(ocpVer string) (string, error) {
|
||||
|
@ -527,46 +527,45 @@ func Test_getPlatformNameFromKubectlOutput(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
want Platform
|
||||
}{
|
||||
{
|
||||
name: "eks",
|
||||
args: args{s: "v1.17.9-eks-4c6976"},
|
||||
want: "eks",
|
||||
want: Platform{Name: "eks", Version: "1.17"},
|
||||
},
|
||||
{
|
||||
name: "gke",
|
||||
args: args{s: "v1.17.6-gke.1"},
|
||||
want: "gke",
|
||||
want: Platform{Name: "gke", Version: "1.17"},
|
||||
},
|
||||
{
|
||||
name: "ack",
|
||||
args: args{s: "v1.18.8-aliyun.1"},
|
||||
want: "aliyun",
|
||||
want: Platform{Name: "aliyun", Version: "1.18"},
|
||||
},
|
||||
{
|
||||
name: "unknown",
|
||||
args: args{s: "v1.17.6"},
|
||||
want: "",
|
||||
want: Platform{},
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
args: args{s: ""},
|
||||
want: "",
|
||||
want: Platform{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := getPlatformNameFromVersion(tt.args.s); got != tt.want {
|
||||
t.Errorf("getPlatformNameFromKubectlOutput() = %v, want %v", got, tt.want)
|
||||
}
|
||||
got := getPlatformInfoFromVersion(tt.args.s)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getPlatformBenchmarkVersion(t *testing.T) {
|
||||
type args struct {
|
||||
platform string
|
||||
platform Platform
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -576,49 +575,63 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
|
||||
{
|
||||
name: "eks",
|
||||
args: args{
|
||||
platform: "eks",
|
||||
platform: Platform{Name: "eks"},
|
||||
},
|
||||
want: "eks-1.0.1",
|
||||
},
|
||||
{
|
||||
name: "gke",
|
||||
name: "gke 1.19",
|
||||
args: args{
|
||||
platform: "gke",
|
||||
platform: Platform{Name: "gke", Version: "1.19"},
|
||||
},
|
||||
want: "gke-1.0",
|
||||
},
|
||||
{
|
||||
name: "gke 1.20",
|
||||
args: args{
|
||||
platform: Platform{Name: "gke", Version: "1.20"},
|
||||
},
|
||||
want: "gke-1.2.0",
|
||||
},
|
||||
{
|
||||
name: "gke 1.22",
|
||||
args: args{
|
||||
platform: Platform{Name: "gke", Version: "1.22"},
|
||||
},
|
||||
want: "gke-1.2.0",
|
||||
},
|
||||
{
|
||||
name: "aliyun",
|
||||
args: args{
|
||||
platform: "aliyun",
|
||||
platform: Platform{Name: "aliyun"},
|
||||
},
|
||||
want: "ack-1.0",
|
||||
},
|
||||
{
|
||||
name: "unknown",
|
||||
args: args{
|
||||
platform: "rh",
|
||||
platform: Platform{Name: "rh"},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
args: args{
|
||||
platform: "",
|
||||
platform: Platform{},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "openshift3",
|
||||
args: args{
|
||||
platform: "ocp-3.10",
|
||||
platform: Platform{Name: "ocp", Version: "3.10"},
|
||||
},
|
||||
want: "rh-0.7",
|
||||
},
|
||||
{
|
||||
name: "openshift4",
|
||||
args: args{
|
||||
platform: "ocp-4.1",
|
||||
platform: Platform{Name: "ocp", Version: "4.1"},
|
||||
},
|
||||
want: "rh-1.0",
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user