From efd65f9839f7379b590452ed31ab8605102904c3 Mon Sep 17 00:00:00 2001 From: Pawel Wieczorek Date: Tue, 17 Sep 2019 15:47:24 +0200 Subject: k8s: Validate API server included admission plugins This patch verifies if CIS Kubernetes Benchmark v1.3.0 sections regarding master node configuration are satisfied (1.1.11 - 1.1.13, 1.1.24, 1.1.27, 1.1.33 and 1.1.36). Issue-ID: SECCOM-235 Change-Id: I920bfd42014b8458126be251648f5bf3dcd84c16 Signed-off-by: Pawel Wieczorek --- test/security/k8s/src/check/cmd/check/check.go | 8 +++ .../k8s/src/check/validators/master/api.go | 77 +++++++++++++++++++++ .../k8s/src/check/validators/master/api_test.go | 80 +++++++++++++++++++++- 3 files changed, 164 insertions(+), 1 deletion(-) (limited to 'test/security') diff --git a/test/security/k8s/src/check/cmd/check/check.go b/test/security/k8s/src/check/cmd/check/check.go index 2ea180628..64c47488c 100644 --- a/test/security/k8s/src/check/cmd/check/check.go +++ b/test/security/k8s/src/check/cmd/check/check.go @@ -53,4 +53,12 @@ func main() { log.Printf("IsSecurePortAbsentOrValid: %t\n", master.IsSecurePortAbsentOrValid(k8sParams)) log.Printf("IsAlwaysAdmitAdmissionControlPluginExcluded: %t\n", master.IsAlwaysAdmitAdmissionControlPluginExcluded(k8sParams)) + + log.Printf("IsAlwaysPullImagesAdmissionControlPluginIncluded: %t\n", master.IsAlwaysPullImagesAdmissionControlPluginIncluded(k8sParams)) + log.Printf("IsDenyEscalatingExecAdmissionControlPluginIncluded: %t\n", master.IsDenyEscalatingExecAdmissionControlPluginIncluded(k8sParams)) + log.Printf("IsSecurityContextDenyAdmissionControlPluginIncluded: %t\n", master.IsSecurityContextDenyAdmissionControlPluginIncluded(k8sParams)) + log.Printf("IsPodSecurityPolicyAdmissionControlPluginIncluded: %t\n", master.IsPodSecurityPolicyAdmissionControlPluginIncluded(k8sParams)) + log.Printf("IsServiceAccountAdmissionControlPluginIncluded: %t\n", master.IsServiceAccountAdmissionControlPluginIncluded(k8sParams)) + log.Printf("IsNodeRestrictionAdmissionControlPluginIncluded: %t\n", master.IsNodeRestrictionAdmissionControlPluginIncluded(k8sParams)) + log.Printf("IsEventRateLimitAdmissionControlPluginIncluded: %t\n", master.IsEventRateLimitAdmissionControlPluginIncluded(k8sParams)) } diff --git a/test/security/k8s/src/check/validators/master/api.go b/test/security/k8s/src/check/validators/master/api.go index 58064ef10..0bed71189 100644 --- a/test/security/k8s/src/check/validators/master/api.go +++ b/test/security/k8s/src/check/validators/master/api.go @@ -138,6 +138,83 @@ func IsAlwaysAdmitAdmissionControlPluginExcluded(params []string) bool { return false } +// IsAlwaysPullImagesAdmissionControlPluginIncluded validates AlwaysPullImages is included in admission control plugins. +func IsAlwaysPullImagesAdmissionControlPluginIncluded(params []string) bool { + if isSingleFlagPresent("--enable-admission-plugins=", params) { + return hasFlagArgumentIncluded("--enable-admission-plugins=", "AlwaysPullImages", params) + } + if isSingleFlagPresent("--admission-control=", params) { + return hasFlagArgumentIncluded("--admission-control=", "AlwaysPullImages", params) + } + return false +} + +// IsDenyEscalatingExecAdmissionControlPluginIncluded validates DenyEscalatingExec is included in admission control plugins. +func IsDenyEscalatingExecAdmissionControlPluginIncluded(params []string) bool { + if isSingleFlagPresent("--enable-admission-plugins=", params) { + return hasFlagArgumentIncluded("--enable-admission-plugins=", "DenyEscalatingExec", params) + } + if isSingleFlagPresent("--admission-control=", params) { + return hasFlagArgumentIncluded("--admission-control=", "DenyEscalatingExec", params) + } + return false +} + +// IsSecurityContextDenyAdmissionControlPluginIncluded validates SecurityContextDeny is included in admission control plugins. +func IsSecurityContextDenyAdmissionControlPluginIncluded(params []string) bool { + if isSingleFlagPresent("--enable-admission-plugins=", params) { + return hasFlagArgumentIncluded("--enable-admission-plugins=", "SecurityContextDeny", params) + } + if isSingleFlagPresent("--admission-control=", params) { + return hasFlagArgumentIncluded("--admission-control=", "SecurityContextDeny", params) + } + return false +} + +// IsPodSecurityPolicyAdmissionControlPluginIncluded validates PodSecurityPolicy is included in admission control plugins. +func IsPodSecurityPolicyAdmissionControlPluginIncluded(params []string) bool { + if isSingleFlagPresent("--enable-admission-plugins=", params) { + return hasFlagArgumentIncluded("--enable-admission-plugins=", "PodSecurityPolicy", params) + } + if isSingleFlagPresent("--admission-control=", params) { + return hasFlagArgumentIncluded("--admission-control=", "PodSecurityPolicy", params) + } + return false +} + +// IsServiceAccountAdmissionControlPluginIncluded validates ServiceAccount is included in admission control plugins. +func IsServiceAccountAdmissionControlPluginIncluded(params []string) bool { + if isSingleFlagPresent("--enable-admission-plugins=", params) { + return hasFlagArgumentIncluded("--enable-admission-plugins=", "ServiceAccount", params) + } + if isSingleFlagPresent("--admission-control=", params) { + return hasFlagArgumentIncluded("--admission-control=", "ServiceAccount", params) + } + return false +} + +// IsNodeRestrictionAdmissionControlPluginIncluded validates NodeRestriction is included in admission control plugins. +func IsNodeRestrictionAdmissionControlPluginIncluded(params []string) bool { + if isSingleFlagPresent("--enable-admission-plugins=", params) { + return hasFlagArgumentIncluded("--enable-admission-plugins=", "NodeRestriction", params) + } + if isSingleFlagPresent("--admission-control=", params) { + return hasFlagArgumentIncluded("--admission-control=", "NodeRestriction", params) + } + return false +} + +// IsEventRateLimitAdmissionControlPluginIncluded validates EventRateLimit is included in admission control plugins. +func IsEventRateLimitAdmissionControlPluginIncluded(params []string) bool { + if isSingleFlagPresent("--enable-admission-plugins=", params) { + return hasFlagArgumentIncluded("--enable-admission-plugins=", "EventRateLimit", params) + } + if isSingleFlagPresent("--admission-control=", params) { + return hasFlagArgumentIncluded("--admission-control=", "EventRateLimit", params) + } + return false +} + // isSingleFlagPresent checks presence of selected flag and whether it was used once. func isSingleFlagPresent(flag string, params []string) bool { found := filterFlags(params, flag) diff --git a/test/security/k8s/src/check/validators/master/api_test.go b/test/security/k8s/src/check/validators/master/api_test.go index f7c6daa52..4e125663a 100644 --- a/test/security/k8s/src/check/validators/master/api_test.go +++ b/test/security/k8s/src/check/validators/master/api_test.go @@ -21,7 +21,8 @@ var _ = Describe("Api", func() { "--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount," + "TaintNodesByCondition,Priority,DefaultTolerationSeconds,DefaultStorageClass," + "PersistentVolumeClaimResize,MutatingAdmissionWebhook,ValidatingAdmissionWebhook," + - "ResourceQuota", + "ResourceQuota,AlwaysPullImages,DenyEscalatingExec,SecurityContextDeny," + + "PodSecurityPolicy,NodeRestriction,EventRateLimit", } // kubeApiServerCasablanca was obtained from virtual environment for testing @@ -227,5 +228,82 @@ var _ = Describe("Api", func() { Entry("Should be absent on Casablanca cluster", kubeApiServerCasablanca, true), Entry("Should be absent on Dublin cluster", kubeApiServerDublin, true), ) + + DescribeTable("AlwaysPullImages admission control plugin", + func(params []string, expected bool) { + Expect(IsAlwaysPullImagesAdmissionControlPluginIncluded(params)).To(Equal(expected)) + }, + Entry("Is not present on insecure cluster", []string{"--enable-admission-plugins=Foo,Bar"}, false), + Entry("Is not present on insecure deprecated cluster", []string{"--admission-control=Foo,Bar"}, false), + Entry("Is not present on Casablanca cluster", kubeApiServerCasablanca, false), + Entry("Is not present on Dublin cluster", kubeApiServerDublin, false), + Entry("Should be present on CIS-compliant cluster", kubeApiServerCISCompliant, true), + ) + + DescribeTable("DenyEscalatingExec admission control plugin", + func(params []string, expected bool) { + Expect(IsDenyEscalatingExecAdmissionControlPluginIncluded(params)).To(Equal(expected)) + }, + Entry("Is not present on insecure cluster", []string{"--enable-admission-plugins=Foo,Bar"}, false), + Entry("Is not present on insecure deprecated cluster", []string{"--admission-control=Foo,Bar"}, false), + Entry("Is not present on Casablanca cluster", kubeApiServerCasablanca, false), + Entry("Is not present on Dublin cluster", kubeApiServerDublin, false), + Entry("Should be present on CIS-compliant cluster", kubeApiServerCISCompliant, true), + ) + + DescribeTable("SecurityContextDeny admission control plugin", + func(params []string, expected bool) { + Expect(IsSecurityContextDenyAdmissionControlPluginIncluded(params)).To(Equal(expected)) + }, + Entry("Is not present on insecure cluster", []string{"--enable-admission-plugins=Foo,Bar"}, false), + Entry("Is not present on insecure deprecated cluster", []string{"--admission-control=Foo,Bar"}, false), + Entry("Is not present on Casablanca cluster", kubeApiServerCasablanca, false), + Entry("Is not present on Dublin cluster", kubeApiServerDublin, false), + Entry("Should be present on CIS-compliant cluster", kubeApiServerCISCompliant, true), + ) + + DescribeTable("PodSecurityPolicy admission control plugin", + func(params []string, expected bool) { + Expect(IsPodSecurityPolicyAdmissionControlPluginIncluded(params)).To(Equal(expected)) + }, + Entry("Is not present on insecure cluster", []string{"--enable-admission-plugins=Foo,Bar"}, false), + Entry("Is not present on insecure deprecated cluster", []string{"--admission-control=Foo,Bar"}, false), + Entry("Is not present on Casablanca cluster", kubeApiServerCasablanca, false), + Entry("Is not present on Dublin cluster", kubeApiServerDublin, false), + Entry("Should be present on CIS-compliant cluster", kubeApiServerCISCompliant, true), + ) + + DescribeTable("ServiceAccount admission control plugin", + func(params []string, expected bool) { + Expect(IsServiceAccountAdmissionControlPluginIncluded(params)).To(Equal(expected)) + }, + Entry("Is not present on insecure cluster", []string{"--enable-admission-plugins=Foo,Bar"}, false), + Entry("Is not present on insecure deprecated cluster", []string{"--admission-control=Foo,Bar"}, false), + Entry("Should be present on CIS-compliant cluster", kubeApiServerCISCompliant, true), + Entry("Should be present on Casablanca cluster", kubeApiServerCasablanca, true), + Entry("Should be present on Dublin cluster", kubeApiServerDublin, true), + ) + + DescribeTable("NodeRestriction admission control plugin", + func(params []string, expected bool) { + Expect(IsNodeRestrictionAdmissionControlPluginIncluded(params)).To(Equal(expected)) + }, + Entry("Is not present on insecure cluster", []string{"--enable-admission-plugins=Foo,Bar"}, false), + Entry("Is not present on insecure deprecated cluster", []string{"--admission-control=Foo,Bar"}, false), + Entry("Is not present on Casablanca cluster", kubeApiServerCasablanca, false), + Entry("Should be present on CIS-compliant cluster", kubeApiServerCISCompliant, true), + Entry("Should be present on Dublin cluster", kubeApiServerDublin, true), + ) + + DescribeTable("EventRateLimit admission control plugin", + func(params []string, expected bool) { + Expect(IsEventRateLimitAdmissionControlPluginIncluded(params)).To(Equal(expected)) + }, + Entry("Is not present on insecure cluster", []string{"--enable-admission-plugins=Foo,Bar"}, false), + Entry("Is not present on insecure deprecated cluster", []string{"--admission-control=Foo,Bar"}, false), + Entry("Is not present on Casablanca cluster", kubeApiServerCasablanca, false), + Entry("Is not present on Dublin cluster", kubeApiServerDublin, false), + Entry("Should be present on CIS-compliant cluster", kubeApiServerCISCompliant, true), + ) }) }) -- cgit 1.2.3-korg