From 4e74a1e24e15b3db2216fb269a58cfc08e598f63 Mon Sep 17 00:00:00 2001 From: Pawel Wieczorek Date: Thu, 19 Sep 2019 16:06:13 +0200 Subject: k8s: Validate API server certificates and keys This patch verifies if CIS Kubernetes Benchmark v1.3.0 sections regarding master node configuration are satisfied (1.1.22, 1.1.25 - 1.1.26 and 1.1.28). Issue-ID: SECCOM-235 Change-Id: Ic61a796653dc868d20fe69c3ed508e7fa8ba52db Signed-off-by: Pawel Wieczorek --- test/security/k8s/src/check/cmd/check/check.go | 5 +++ .../k8s/src/check/validators/master/api.go | 23 ++++++++++ .../k8s/src/check/validators/master/api_test.go | 51 ++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/test/security/k8s/src/check/cmd/check/check.go b/test/security/k8s/src/check/cmd/check/check.go index d124b8708..028843734 100644 --- a/test/security/k8s/src/check/cmd/check/check.go +++ b/test/security/k8s/src/check/cmd/check/check.go @@ -74,4 +74,9 @@ func main() { log.Printf("IsKubeletCertificateAuthoritySet: %t\n", master.IsKubeletCertificateAuthoritySet(k8sParams)) log.Printf("IsClientCertificateAuthoritySet: %t\n", master.IsClientCertificateAuthoritySet(k8sParams)) log.Printf("IsEtcdCertificateAuthoritySet: %t\n", master.IsEtcdCertificateAuthoritySet(k8sParams)) + + log.Printf("IsServiceAccountKeySet: %t\n", master.IsServiceAccountKeySet(k8sParams)) + log.Printf("IsKubeletClientCertificateAndKeySet: %t\n", master.IsKubeletClientCertificateAndKeySet(k8sParams)) + log.Printf("IsEtcdCertificateAndKeySet: %t\n", master.IsEtcdCertificateAndKeySet(k8sParams)) + log.Printf("IsTLSCertificateAndKeySet: %t\n", master.IsTLSCertificateAndKeySet(k8sParams)) } diff --git a/test/security/k8s/src/check/validators/master/api.go b/test/security/k8s/src/check/validators/master/api.go index 4a70e5337..95a02d17d 100644 --- a/test/security/k8s/src/check/validators/master/api.go +++ b/test/security/k8s/src/check/validators/master/api.go @@ -278,6 +278,29 @@ func IsEtcdCertificateAuthoritySet(params []string) bool { return hasSingleFlagNonemptyArgument("--etcd-cafile", params) } +// IsServiceAccountKeySet validates there is single "--service-account-key-file" flag and has non-empty argument. +func IsServiceAccountKeySet(params []string) bool { + return hasSingleFlagNonemptyArgument("--service-account-key-file", params) +} + +// IsKubeletClientCertificateAndKeySet validates there are single "--kubelet-client-certificate" and "--kubelet-client-key" flags and have non-empty arguments. +func IsKubeletClientCertificateAndKeySet(params []string) bool { + return hasSingleFlagNonemptyArgument("--kubelet-client-certificate", params) && + hasSingleFlagNonemptyArgument("--kubelet-client-key", params) +} + +// IsEtcdCertificateAndKeySet validates there are single "--etcd-certfile" and "--etcd-keyfile" flags and have non-empty arguments. +func IsEtcdCertificateAndKeySet(params []string) bool { + return hasSingleFlagNonemptyArgument("--etcd-certfile", params) && + hasSingleFlagNonemptyArgument("--etcd-keyfile", params) +} + +// IsTLSCertificateAndKeySet validates there are single "--tls-cert-file" and "--tls-private-key-file" flags and have non-empty arguments. +func IsTLSCertificateAndKeySet(params []string) bool { + return hasSingleFlagNonemptyArgument("--tls-cert-file", params) && + hasSingleFlagNonemptyArgument("--tls-private-key-file", params) +} + // hasSingleFlagNonemptyArgument checks whether selected flag was used once and has non-empty argument. func hasSingleFlagNonemptyArgument(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 f0db8b776..f9eb943b3 100644 --- a/test/security/k8s/src/check/validators/master/api_test.go +++ b/test/security/k8s/src/check/validators/master/api_test.go @@ -31,6 +31,13 @@ var _ = Describe("Api", func() { "--kubelet-certificate-authority=TrustedCA", "--client-ca-file=/etc/kubernetes/ssl/ca.pem", "--etcd-cafile=/etc/kubernetes/etcd/ca.pem", + "--service-account-key-file=/etc/kubernetes/ssl/kube-service-account-token-key.pem", + "--kubelet-client-certificate=/etc/kubernetes/ssl/cert.pem", + "--kubelet-client-key=/etc/kubernetes/ssl/key.pem", + "--etcd-certfile=/etc/kubernetes/etcd/cert.pem", + "--etcd-keyfile=/etc/kubernetes/etcd/key.pem", + "--tls-cert-file=/etc/kubernetes/ssl/cert.pem", + "--tls-private-key-file=/etc/kubernetes/ssl/key.pem", } // kubeApiServerCasablanca was obtained from virtual environment for testing @@ -240,6 +247,50 @@ var _ = Describe("Api", func() { Entry("Should be present on Casablanca cluster", kubeApiServerCasablanca, true), Entry("Should be present on Dublin cluster", kubeApiServerDublin, true), ) + + DescribeTable("Service account key", + func(params []string, expected bool) { + Expect(IsServiceAccountKeySet(params)).To(Equal(expected)) + }, + Entry("Is absent on insecure cluster", []string{}, false), + Entry("Is empty on insecure cluster", []string{"--service-account-key-file="}, false), + Entry("Is absent 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("Kubelet client certificate and key", + func(params []string, expected bool) { + Expect(IsKubeletClientCertificateAndKeySet(params)).To(Equal(expected)) + }, + Entry("Is absent on insecure cluster", []string{}, false), + Entry("Is empty on insecure cluster", []string{"--kubelet-client-certificate= --kubelet-client-key="}, 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("Etcd certificate and key", + func(params []string, expected bool) { + Expect(IsEtcdCertificateAndKeySet(params)).To(Equal(expected)) + }, + Entry("Is absent on insecure cluster", []string{}, false), + Entry("Is empty on insecure cluster", []string{"--etcd-certfile= --etcd-keyfile="}, 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("TLS certificate and key", + func(params []string, expected bool) { + Expect(IsTLSCertificateAndKeySet(params)).To(Equal(expected)) + }, + Entry("Is absent on insecure cluster", []string{}, false), + Entry("Is empty on insecure cluster", []string{"--tls-cert-file= --tls-private-key-file="}, 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), + ) }) Describe("Address and port flags", func() { -- cgit 1.2.3-korg