aboutsummaryrefslogtreecommitdiffstats
path: root/test/security/k8s
diff options
context:
space:
mode:
Diffstat (limited to 'test/security/k8s')
-rw-r--r--test/security/k8s/src/check/check.go45
-rw-r--r--test/security/k8s/src/check/cmd/check/check.go14
-rw-r--r--test/security/k8s/src/check/rancher/rancher.go36
-rw-r--r--test/security/k8s/src/check/raw/raw.go31
-rw-r--r--test/security/k8s/src/check/validators/master/master.go97
5 files changed, 142 insertions, 81 deletions
diff --git a/test/security/k8s/src/check/check.go b/test/security/k8s/src/check/check.go
new file mode 100644
index 000000000..c185887d7
--- /dev/null
+++ b/test/security/k8s/src/check/check.go
@@ -0,0 +1,45 @@
+package check
+
+// Informer collects and returns information on cluster.
+type Informer interface {
+ // GetAPIParams returns API server parameters.
+ GetAPIParams() ([]string, error)
+}
+
+// Command represents commands run on cluster.
+type Command int
+
+const (
+ // APIProcess represents API server command ("kube-apiserver").
+ APIProcess Command = iota
+)
+
+func (c Command) String() string {
+ names := [...]string{
+ "kube-apiserver",
+ }
+
+ if c < APIProcess || c > APIProcess {
+ return "exit"
+ }
+ return names[c]
+}
+
+// Service represents services run on Rancher-based cluster.
+type Service int
+
+const (
+ // APIService represents API server service ("kubernetes/kubernetes").
+ APIService Service = iota
+)
+
+func (s Service) String() string {
+ names := [...]string{
+ "kubernetes/kubernetes",
+ }
+
+ if s < APIService || s > APIService {
+ return ""
+ }
+ return names[s]
+}
diff --git a/test/security/k8s/src/check/cmd/check/check.go b/test/security/k8s/src/check/cmd/check/check.go
index 80a17f0c5..40e3a092c 100644
--- a/test/security/k8s/src/check/cmd/check/check.go
+++ b/test/security/k8s/src/check/cmd/check/check.go
@@ -4,6 +4,7 @@ import (
"flag"
"log"
+ "check"
"check/rancher"
"check/raw"
"check/validators/master"
@@ -25,23 +26,20 @@ func main() {
*rke = true
}
- var (
- k8sParams []string
- err error
- )
+ var info check.Informer
switch {
case *ranchercli:
- k8sParams, err = rancher.GetK8sParams()
+ info = &rancher.Rancher{}
case *rke:
- k8sParams, err = raw.GetK8sParams()
+ info = &raw.Raw{}
default:
log.Fatal("Missing cluster access method.")
}
+ apiParams, err := info.GetAPIParams()
if err != nil {
log.Fatal(err)
}
-
- master.Check(k8sParams)
+ master.CheckAPI(apiParams)
}
diff --git a/test/security/k8s/src/check/rancher/rancher.go b/test/security/k8s/src/check/rancher/rancher.go
index d60b73b65..d77f15445 100644
--- a/test/security/k8s/src/check/rancher/rancher.go
+++ b/test/security/k8s/src/check/rancher/rancher.go
@@ -3,8 +3,10 @@ package rancher
import (
"bytes"
- "errors"
+ "fmt"
"os/exec"
+
+ "check"
)
const (
@@ -16,32 +18,40 @@ const (
cmdDockerCmdPs = "ps"
cmdDockerCmdPsParams = "--no-trunc"
cmdDockerCmdPsFilter = "--filter"
- cmdDockerCmdPsFilterArgs = "label=io.rancher.stack_service.name=kubernetes/kubernetes"
+ cmdDockerCmdPsFilterArgs = "label=io.rancher.stack_service.name="
cmdDockerCmdPsFormat = "--format"
cmdDockerCmdPsFormatArgs = "{{.Command}}"
- k8sProcess = "kube-apiserver"
)
-// GetK8sParams returns parameters of running Kubernetes API server.
+// Rancher implements Informer interface.
+type Rancher struct {
+ check.Informer
+}
+
+// GetAPIParams returns parameters of running Kubernetes API server.
// It queries default environment set in configuration file.
-func GetK8sParams() ([]string, error) {
+func (r *Rancher) GetAPIParams() ([]string, error) {
+ return getProcessParams(check.APIProcess, check.APIService)
+}
+
+func getProcessParams(process check.Command, service check.Service) ([]string, error) {
hosts, err := listHosts()
if err != nil {
return []string{}, err
}
for _, host := range hosts {
- cmd, err := getK8sCmd(host)
+ cmd, err := getPsCmdOutput(host, service)
if err != nil {
return []string{}, err
}
if len(cmd) > 0 {
- i := bytes.Index(cmd, []byte(k8sProcess))
+ i := bytes.Index(cmd, []byte(process.String()))
if i == -1 {
- return []string{}, errors.New("missing " + k8sProcess + " command")
+ return []string{}, fmt.Errorf("missing %s command", process)
}
- return btos(cmd[i+len(k8sProcess):]), nil
+ return btos(cmd[i+len(process.String()):]), nil
}
}
return []string{}, nil
@@ -58,17 +68,17 @@ func listHosts() ([]string, error) {
return btos(out), nil
}
-// getK8sCmd returns running Kubernetes API server command with its parameters.
+// getPsCmdOutput returns running Kubernetes service command with its parameters.
// It queries default environment set in configuration file.
-func getK8sCmd(host string) ([]byte, error) {
+func getPsCmdOutput(host string, service check.Service) ([]byte, error) {
// Following is equivalent to:
// $ rancher --host $HOST \
// docker ps --no-trunc \
- // --filter "label=io.rancher.stack_service.name=kubernetes/kubernetes" \
+ // --filter "label=io.rancher.stack_service.name=$SERVICE" \
// --format "{{.Command}}"
cmd := exec.Command(bin, paramHost, host,
cmdDocker, cmdDockerCmdPs, cmdDockerCmdPsParams,
- cmdDockerCmdPsFilter, cmdDockerCmdPsFilterArgs,
+ cmdDockerCmdPsFilter, cmdDockerCmdPsFilterArgs+service.String(),
cmdDockerCmdPsFormat, cmdDockerCmdPsFormatArgs)
out, err := cmd.Output()
if err != nil {
diff --git a/test/security/k8s/src/check/raw/raw.go b/test/security/k8s/src/check/raw/raw.go
index 4efa1d4f8..2a9f0a17f 100644
--- a/test/security/k8s/src/check/raw/raw.go
+++ b/test/security/k8s/src/check/raw/raw.go
@@ -3,7 +3,7 @@ package raw
import (
"bytes"
- "errors"
+ "fmt"
"io/ioutil"
"os/user"
"path/filepath"
@@ -11,6 +11,7 @@ import (
"golang.org/x/crypto/ssh"
kh "golang.org/x/crypto/ssh/knownhosts"
+ "check"
"check/config"
)
@@ -19,15 +20,21 @@ const (
etcd = "etcd"
worker = "worker"
- k8sProcess = "kube-apiserver"
- dockerInspectCmd = "docker inspect " + k8sProcess + " --format {{.Args}}"
-
knownHostsFile = "~/.ssh/known_hosts"
)
-// GetK8sParams returns parameters of running Kubernetes API servers.
+// Raw implements Informer interface.
+type Raw struct {
+ check.Informer
+}
+
+// GetAPIParams returns parameters of running Kubernetes API servers.
// It queries only cluster nodes with "controlplane" role.
-func GetK8sParams() ([]string, error) {
+func (r *Raw) GetAPIParams() ([]string, error) {
+ return getProcessParams(check.APIProcess)
+}
+
+func getProcessParams(process check.Command) ([]string, error) {
nodes, err := config.GetNodesInfo()
if err != nil {
return []string{}, err
@@ -35,17 +42,17 @@ func GetK8sParams() ([]string, error) {
for _, node := range nodes {
if isControlplaneNode(node.Role) {
- cmd, err := getK8sCmd(node)
+ cmd, err := getInspectCmdOutput(node, process)
if err != nil {
return []string{}, err
}
if len(cmd) > 0 {
- i := bytes.Index(cmd, []byte(k8sProcess))
+ i := bytes.Index(cmd, []byte(process.String()))
if i == -1 {
- return []string{}, errors.New("missing " + k8sProcess + " command")
+ return []string{}, fmt.Errorf("missing %s command", process)
}
- return btos(cmd[i+len(k8sProcess):]), nil
+ return btos(cmd[i+len(process.String()):]), nil
}
}
}
@@ -62,7 +69,7 @@ func isControlplaneNode(roles []string) bool {
return false
}
-func getK8sCmd(node config.NodeInfo) ([]byte, error) {
+func getInspectCmdOutput(node config.NodeInfo, cmd check.Command) ([]byte, error) {
path, err := expandPath(node.SSHKeyPath)
if err != nil {
return nil, err
@@ -95,7 +102,7 @@ func getK8sCmd(node config.NodeInfo) ([]byte, error) {
}
defer conn.Close()
- out, err := runCommand(dockerInspectCmd, conn)
+ out, err := runCommand(fmt.Sprintf("docker inspect %s --format {{.Args}}", cmd), conn)
if err != nil {
return nil, err
}
diff --git a/test/security/k8s/src/check/validators/master/master.go b/test/security/k8s/src/check/validators/master/master.go
index e9dc66cc6..ff3b79648 100644
--- a/test/security/k8s/src/check/validators/master/master.go
+++ b/test/security/k8s/src/check/validators/master/master.go
@@ -6,52 +6,53 @@ import (
"check/validators/master/api"
)
-// Check validates master node complies with CIS guideliness.
-func Check(k8sParams []string) {
- log.Printf("IsBasicAuthFileAbsent: %t\n", api.IsBasicAuthFileAbsent(k8sParams))
- log.Printf("IsTokenAuthFileAbsent: %t\n", api.IsTokenAuthFileAbsent(k8sParams))
- log.Printf("IsInsecureAllowAnyTokenAbsent: %t\n", api.IsInsecureAllowAnyTokenAbsent(k8sParams))
-
- log.Printf("IsAnonymousAuthDisabled: %t\n", api.IsAnonymousAuthDisabled(k8sParams))
- log.Printf("IsInsecurePortUnbound: %t\n", api.IsInsecurePortUnbound(k8sParams))
- log.Printf("IsProfilingDisabled: %t\n", api.IsProfilingDisabled(k8sParams))
- log.Printf("IsRepairMalformedUpdatesDisabled: %t\n", api.IsRepairMalformedUpdatesDisabled(k8sParams))
- log.Printf("IsServiceAccountLookupEnabled: %t\n", api.IsServiceAccountLookupEnabled(k8sParams))
-
- log.Printf("IsKubeletHTTPSAbsentOrEnabled: %t\n", api.IsKubeletHTTPSAbsentOrEnabled(k8sParams))
- log.Printf("IsInsecureBindAddressAbsentOrLoopback: %t\n", api.IsInsecureBindAddressAbsentOrLoopback(k8sParams))
- log.Printf("IsSecurePortAbsentOrValid: %t\n", api.IsSecurePortAbsentOrValid(k8sParams))
-
- log.Printf("IsAlwaysAdmitAdmissionControlPluginExcluded: %t\n", api.IsAlwaysAdmitAdmissionControlPluginExcluded(k8sParams))
-
- log.Printf("IsAlwaysPullImagesAdmissionControlPluginIncluded: %t\n", api.IsAlwaysPullImagesAdmissionControlPluginIncluded(k8sParams))
- log.Printf("IsDenyEscalatingExecAdmissionControlPluginIncluded: %t\n", api.IsDenyEscalatingExecAdmissionControlPluginIncluded(k8sParams))
- log.Printf("IsSecurityContextDenyAdmissionControlPluginIncluded: %t\n", api.IsSecurityContextDenyAdmissionControlPluginIncluded(k8sParams))
- log.Printf("IsPodSecurityPolicyAdmissionControlPluginIncluded: %t\n", api.IsPodSecurityPolicyAdmissionControlPluginIncluded(k8sParams))
- log.Printf("IsServiceAccountAdmissionControlPluginIncluded: %t\n", api.IsServiceAccountAdmissionControlPluginIncluded(k8sParams))
- log.Printf("IsNodeRestrictionAdmissionControlPluginIncluded: %t\n", api.IsNodeRestrictionAdmissionControlPluginIncluded(k8sParams))
- log.Printf("IsEventRateLimitAdmissionControlPluginIncluded: %t\n", api.IsEventRateLimitAdmissionControlPluginIncluded(k8sParams))
-
- log.Printf("IsNamespaceLifecycleAdmissionControlPluginNotExcluded: %t\n", api.IsNamespaceLifecycleAdmissionControlPluginNotExcluded(k8sParams))
-
- log.Printf("IsAlwaysAllowAuthorizationModeExcluded: %t\n", api.IsAlwaysAllowAuthorizationModeExcluded(k8sParams))
- log.Printf("IsNodeAuthorizationModeIncluded: %t\n", api.IsNodeAuthorizationModeIncluded(k8sParams))
-
- log.Printf("IsAuditLogPathSet: %t\n", api.IsAuditLogPathSet(k8sParams))
- log.Printf("IsAuditLogMaxAgeValid: %t\n", api.IsAuditLogMaxAgeValid(k8sParams))
- log.Printf("IsAuditLogMaxBackupValid: %t\n", api.IsAuditLogMaxBackupValid(k8sParams))
- log.Printf("IsAuditLogMaxSizeValid: %t\n", api.IsAuditLogMaxSizeValid(k8sParams))
-
- log.Printf("IsRequestTimeoutValid: %t\n", api.IsRequestTimeoutValid(k8sParams))
-
- log.Printf("IsKubeletCertificateAuthoritySet: %t\n", api.IsKubeletCertificateAuthoritySet(k8sParams))
- log.Printf("IsClientCertificateAuthoritySet: %t\n", api.IsClientCertificateAuthoritySet(k8sParams))
- log.Printf("IsEtcdCertificateAuthoritySet: %t\n", api.IsEtcdCertificateAuthoritySet(k8sParams))
-
- log.Printf("IsServiceAccountKeySet: %t\n", api.IsServiceAccountKeySet(k8sParams))
- log.Printf("IsKubeletClientCertificateAndKeySet: %t\n", api.IsKubeletClientCertificateAndKeySet(k8sParams))
- log.Printf("IsEtcdCertificateAndKeySet: %t\n", api.IsEtcdCertificateAndKeySet(k8sParams))
- log.Printf("IsTLSCertificateAndKeySet: %t\n", api.IsTLSCertificateAndKeySet(k8sParams))
-
- log.Printf("IsStrongCryptoCipherInUse: %t\n", api.IsStrongCryptoCipherInUse(k8sParams))
+// CheckAPI validates API server complies with CIS guideliness.
+func CheckAPI(params []string) {
+ log.Println("==> API:")
+ log.Printf("IsBasicAuthFileAbsent: %t\n", api.IsBasicAuthFileAbsent(params))
+ log.Printf("IsTokenAuthFileAbsent: %t\n", api.IsTokenAuthFileAbsent(params))
+ log.Printf("IsInsecureAllowAnyTokenAbsent: %t\n", api.IsInsecureAllowAnyTokenAbsent(params))
+
+ log.Printf("IsAnonymousAuthDisabled: %t\n", api.IsAnonymousAuthDisabled(params))
+ log.Printf("IsInsecurePortUnbound: %t\n", api.IsInsecurePortUnbound(params))
+ log.Printf("IsProfilingDisabled: %t\n", api.IsProfilingDisabled(params))
+ log.Printf("IsRepairMalformedUpdatesDisabled: %t\n", api.IsRepairMalformedUpdatesDisabled(params))
+ log.Printf("IsServiceAccountLookupEnabled: %t\n", api.IsServiceAccountLookupEnabled(params))
+
+ log.Printf("IsKubeletHTTPSAbsentOrEnabled: %t\n", api.IsKubeletHTTPSAbsentOrEnabled(params))
+ log.Printf("IsInsecureBindAddressAbsentOrLoopback: %t\n", api.IsInsecureBindAddressAbsentOrLoopback(params))
+ log.Printf("IsSecurePortAbsentOrValid: %t\n", api.IsSecurePortAbsentOrValid(params))
+
+ log.Printf("IsAlwaysAdmitAdmissionControlPluginExcluded: %t\n", api.IsAlwaysAdmitAdmissionControlPluginExcluded(params))
+
+ log.Printf("IsAlwaysPullImagesAdmissionControlPluginIncluded: %t\n", api.IsAlwaysPullImagesAdmissionControlPluginIncluded(params))
+ log.Printf("IsDenyEscalatingExecAdmissionControlPluginIncluded: %t\n", api.IsDenyEscalatingExecAdmissionControlPluginIncluded(params))
+ log.Printf("IsSecurityContextDenyAdmissionControlPluginIncluded: %t\n", api.IsSecurityContextDenyAdmissionControlPluginIncluded(params))
+ log.Printf("IsPodSecurityPolicyAdmissionControlPluginIncluded: %t\n", api.IsPodSecurityPolicyAdmissionControlPluginIncluded(params))
+ log.Printf("IsServiceAccountAdmissionControlPluginIncluded: %t\n", api.IsServiceAccountAdmissionControlPluginIncluded(params))
+ log.Printf("IsNodeRestrictionAdmissionControlPluginIncluded: %t\n", api.IsNodeRestrictionAdmissionControlPluginIncluded(params))
+ log.Printf("IsEventRateLimitAdmissionControlPluginIncluded: %t\n", api.IsEventRateLimitAdmissionControlPluginIncluded(params))
+
+ log.Printf("IsNamespaceLifecycleAdmissionControlPluginNotExcluded: %t\n", api.IsNamespaceLifecycleAdmissionControlPluginNotExcluded(params))
+
+ log.Printf("IsAlwaysAllowAuthorizationModeExcluded: %t\n", api.IsAlwaysAllowAuthorizationModeExcluded(params))
+ log.Printf("IsNodeAuthorizationModeIncluded: %t\n", api.IsNodeAuthorizationModeIncluded(params))
+
+ log.Printf("IsAuditLogPathSet: %t\n", api.IsAuditLogPathSet(params))
+ log.Printf("IsAuditLogMaxAgeValid: %t\n", api.IsAuditLogMaxAgeValid(params))
+ log.Printf("IsAuditLogMaxBackupValid: %t\n", api.IsAuditLogMaxBackupValid(params))
+ log.Printf("IsAuditLogMaxSizeValid: %t\n", api.IsAuditLogMaxSizeValid(params))
+
+ log.Printf("IsRequestTimeoutValid: %t\n", api.IsRequestTimeoutValid(params))
+
+ log.Printf("IsKubeletCertificateAuthoritySet: %t\n", api.IsKubeletCertificateAuthoritySet(params))
+ log.Printf("IsClientCertificateAuthoritySet: %t\n", api.IsClientCertificateAuthoritySet(params))
+ log.Printf("IsEtcdCertificateAuthoritySet: %t\n", api.IsEtcdCertificateAuthoritySet(params))
+
+ log.Printf("IsServiceAccountKeySet: %t\n", api.IsServiceAccountKeySet(params))
+ log.Printf("IsKubeletClientCertificateAndKeySet: %t\n", api.IsKubeletClientCertificateAndKeySet(params))
+ log.Printf("IsEtcdCertificateAndKeySet: %t\n", api.IsEtcdCertificateAndKeySet(params))
+ log.Printf("IsTLSCertificateAndKeySet: %t\n", api.IsTLSCertificateAndKeySet(params))
+
+ log.Printf("IsStrongCryptoCipherInUse: %t\n", api.IsStrongCryptoCipherInUse(params))
}