diff --git a/cfg/gke-stig-kubernetes-v2r2/controlplane.yaml b/cfg/gke-stig-kubernetes-v2r2/controlplane.yaml index b6532af..37b3b70 100644 --- a/cfg/gke-stig-kubernetes-v2r2/controlplane.yaml +++ b/cfg/gke-stig-kubernetes-v2r2/controlplane.yaml @@ -8,54 +8,12 @@ groups: - id: 2.1 text: "DISA Category Code I - API Server Security" checks: - - id: V-242378 - text: "The Kubernetes API Server must use TLS 1.2, at a minimum, to protect the confidentiality of sensitive data during electronic dissemination." - audit: "grep -i tls-min-version /etc/kubernetes/manifests/kube-apiserver.yaml" - tests: - test_items: - - flag: "--tls-min-version" - compare: - op: nothave - value: "VersionTLS10" - - flag: "--tls-min-version" - compare: - op: nothave - value: "VersionTLS11" - remediation: | - Edit the Kubernetes API Server manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Set the value of "--tls-min-version" to "VersionTLS12" or higher. - scored: true - - id: V-242388 - text: "The Kubernetes API server must not have the insecure bind address set." - audit: "grep -i insecure-bind-address /etc/kubernetes/manifests/kube-apiserver.yaml" - tests: - test_items: - - flag: "--insecure-bind-address" - set: false - remediation: | - Edit the Kubernetes API Server manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Remove the value of "--insecure-bind-address" setting. - scored: true - - - id: V-242389 - text: "The Kubernetes API server must have the secure port set." - audit: "grep -i secure-port /etc/kubernetes/manifests/kube-apiserver.yaml" - tests: - test_items: - - flag: "--secure-port" - compare: - op: gt - value: "0" - remediation: | - Edit the Kubernetes API Server manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Set the value of "--secure-port" to a value greater than "0". - scored: true - - - id: V-242390 # Similar to CIS 3.2.1 text: "The Kubernetes API server must have anonymous authentication disabled (Automated)" - audit: "/bin/ps -fC $kubeletbin" - audit_config: "/bin/cat $kubeletconf" + audit: "/bin/ps -fC kubelet" + # audit: "/bin/ps -fC $kubeletbin" + audit_config: "/bin/cat /etc/kubernetes/kubelet-config.yaml" + # audit_config: "/bin/cat $kubeletconf" tests: test_items: - flag: "--anonymous-auth" @@ -116,32 +74,23 @@ groups: - id: 2.2 text: "DISA Category Code II - Controller Manager Security" checks: - - id: V-242381 - text: "The Kubernetes Controller Manager must create unique service accounts for each work payload. (Manual)" - type: "manual" - remediation: | - Create explicit service accounts wherever a Kubernetes workload requires specific access - to the Kubernetes API server. - Modify the configuration of each default service account to include this value - automountServiceAccountToken: false - scored: false - - id: V-242376 - text: "The Kubernetes Controller Manager must use TLS 1.2, at a minimum, to protect the confidentiality of sensitive data during electronic dissemination." - audit: "grep -i tls-min-version /etc/kubernetes/manifests/kube-controller-manager.yaml" - tests: - test_items: - - flag: "--tls-min-version" - compare: - op: nothave - value: "VersionTLS10" - - flag: "--tls-min-version" - compare: - op: nothave - value: "VersionTLS11" - remediation: | - Edit the Kubernetes Controller Manager manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Set the value of "--tls-min-version" to "VersionTLS12" or higher. - scored: true + # - id: V-242376 + # text: "The Kubernetes Controller Manager must use TLS 1.2, at a minimum, to protect the confidentiality of sensitive data during electronic dissemination." + # audit: "grep -i tls-min-version /etc/kubernetes/manifests/kube-controller-manager.yaml" + # tests: + # test_items: + # - flag: "--tls-min-version" + # compare: + # op: nothave + # value: "VersionTLS10" + # - flag: "--tls-min-version" + # compare: + # op: nothave + # value: "VersionTLS11" + # remediation: | + # Edit the Kubernetes Controller Manager manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. + # Set the value of "--tls-min-version" to "VersionTLS12" or higher. + - id: V-242443 text: " Kubernetes must contain the latest updates as authorized by IAVMs, CTOs, DTMs, and STIGs. (Manual)" type: "manual" diff --git a/cfg/gke-stig-kubernetes-v2r2/managedservices.yaml b/cfg/gke-stig-kubernetes-v2r2/managedservices.yaml index f9abd6d..1b27c74 100644 --- a/cfg/gke-stig-kubernetes-v2r2/managedservices.yaml +++ b/cfg/gke-stig-kubernetes-v2r2/managedservices.yaml @@ -8,42 +8,13 @@ groups: - id: 5.1 text: "DISA Category Code I" checks: - # TODO: Validate this one - id: V-242386 - text: "The Kubernetes API server must have the insecure port flag disabled." - audit: "grep -i insecure-port /etc/kubernetes/manifests/kube-apiserver.yaml" - tests: - test_items: - - flag: "--insecure-port" - compare: - op: eq - value: "0" - remediation: | - Edit the Kubernetes API Server manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Set the value of "--insecure-port" to "0". - Note: The "--insecure-port" flag has been deprecated and can only be set to "0". This flag will be removed in Kubernetes v1.24. - scored: false + text: "The Kubernetes API server must have the insecure port flag disabled | Component of GKE Control Plane" + type: "skip" - # - id: V-242386 - # text: "The Kubernetes API server must have the insecure port flag disabled | Component of GKE Control Plane" - # type: "skip" - - # TODO: Validate this one - id: V-242388 - text: "The Kubernetes API server must not have the insecure bind address set." - audit: "grep -i insecure-bind-address /etc/kubernetes/manifests/kube-apiserver.yaml" - tests: - test_items: - - flag: "--insecure-bind-address" - set: false - remediation: | - Edit the Kubernetes API Server manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Remove the value of "--insecure-bind-address" setting. - scored: false - - # - id: V-242388 - # text: "The Kubernetes API server must have the insecure bind address not set | Component of GKE Control Plane" - # type: "skip" + text: "The Kubernetes API server must have the insecure bind address not set | Component of GKE Control Plane" + type: "skip" # TODO Verify this one (can't find it like on the aws side https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html) - id: V-242436 @@ -101,63 +72,17 @@ groups: text: "The Kubernetes API Server must enable Node,RBAC as the authorization mode | Component of GKE Control Plane" type: "skip" - # TODO: Move to controlplane if this works in GKE - id: V-242384 - text: "The Kubernetes Scheduler must have secure binding." - audit: "grep -i bind-address /etc/kubernetes/manifests/kube-scheduler.yaml" - tests: - test_items: - - flag: "--bind-address" - compare: - op: eq - value: "127.0.0.1" - remediation: | - Edit the Kubernetes Scheduler manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Set the argument "--bind-address" to "127.0.0.1". - scored: false + text: "The Kubernetes Scheduler must have secure binding | Component of GKE Control Plane" + type: "skip" - # - id: V-242384 - # text: "The Kubernetes Scheduler must have secure binding | Component of GKE Control Plane" - # type: "skip" - - - # TODO: Move to controlplane if this works in GKE - id: V-242385 - text: "The Kubernetes Controller Manager must have secure binding." - audit: "grep -i bind-address /etc/kubernetes/manifests/kube-controller-manager.yaml" - tests: - test_items: - - flag: "--bind-address" - compare: - op: eq - value: "127.0.0.1" - remediation: | - Edit the Kubernetes Controller Manager manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Set the argument "--bind-address" to "127.0.0.1". - scored: false + text: "The Kubernetes Controller Manager must have secure binding | Component of GKE Control Plane" + type: "skip" - # - id: V-242385 - # text: "The Kubernetes Controller Manager must have secure binding | Component of GKE Control Plane" - # type: "skip" - - # TODO: Move to controlplane if this works in GKE - id: V-242389 - text: "The Kubernetes API server must have the secure port set." - audit: "grep -i secure-port /etc/kubernetes/manifests/kube-apiserver.yaml" - tests: - test_items: - - flag: "--secure-port" - compare: - op: gt - value: "0" - remediation: | - Edit the Kubernetes API Server manifest file in the /etc/kubernetes/manifests directory on the Kubernetes Control Plane. - Set the value of "--secure-port" to a value greater than "0". - scored: false - - # - id: V-242389 - # text: "The Kubernetes API server must have the secure port set | Component of EKS Control Plane" - # type: "skip" + text: "The Kubernetes API server must have the secure port set | Component of EKS Control Plane" + type: "skip" # TODO: Didn't actually see this one in the k8s stig file # - id: V-242401 diff --git a/cfg/gke-stig-kubernetes-v2r2/node.yaml b/cfg/gke-stig-kubernetes-v2r2/node.yaml index 4a8ffde..5802411 100644 --- a/cfg/gke-stig-kubernetes-v2r2/node.yaml +++ b/cfg/gke-stig-kubernetes-v2r2/node.yaml @@ -157,31 +157,9 @@ groups: systemctl restart kubelet.service systemctl status kubelet -l scored: true - # TODO Verify this, low confidence this will work - - id: V-242393 - text: "Kubernetes Worker Nodes must not have sshd service running. (Automated)" - audit: '/bin/sh -c ''systemctl show -p ActiveState sshd'' ' - tests: - test_items: - - flag: ActiveState - compare: - op: eq - value: inactive - remediation: | - To stop the sshd service, run the command: systemctl stop sshd - scored: true - # TODO Verify this, low confidence this will work - - id: V-242394 - text: "Kubernetes Worker Nodes must not have the sshd service enabled. (Automated)" - audit: "/bin/sh -c 'systemctl is-enabled sshd.service'" - tests: - test_items: - - flag: "disabled" - remediation: | - To disable the sshd service, run the command: - chkconfig sshd off - scored: true + # TODO: Verify this, probably requires rbac permissions using kubectl + # This needs proper permissions set, TODO!! - id: V-242395 text: "Kubernetes dashboard must not be enabled." audit: "kubectl get pods --all-namespaces -l k8s-app=kubernetes-dashboard" @@ -193,7 +171,8 @@ groups: Delete the Kubernetes dashboard deployment with the following command: kubectl delete deployment kubernetes-dashboard --namespace=kube-system scored: true - # TODO This could be automated, but requires a little more effort or adding jq to the docker image + + # TODO This could be automated, but requires a little more effort or adding jq to the docker image # maybe test path will work - id: V-242396 text: "Kubernetes Kubectl cp command must give expected access and results. (Manual)" @@ -202,20 +181,24 @@ groups: If any Worker nodes are not using kubectl version 1.12.9 or newer, this is a finding. Upgrade the Master and Worker nodes to the latest version of kubectl. scored: false + - id: V-242397 - text: "The Kubernetes kubelet static PodPath must not enable static pods (Automated)" - audit: "/bin/ps -fC $kubeletbin" - audit_config: "/bin/cat $kubeletconf" + text: "The Kubernetes kubelet staticPodPath must not enable static pods." + audit: "ps -ef | grep $kubeletbin | grep -- --config" tests: + bin_op: or test_items: + - flag: "staticPodPath" + set: false - path: '{.staticPodPath}' set: false remediation: | - Edit $kubeletconf on each node to to remove the staticPodPath - Based on your system, restart the kubelet service. For example, - systemctl daemon-reload - systemctl restart kubelet.service + Edit the Kubernetes kubelet configuration file. + Remove the setting "staticPodPath". + Restart the kubelet service using: + systemctl daemon-reload && systemctl restart kubelet scored: true + - id: V-242398 text: "Kubernetes DynamicAuditing must not be enabled. (Automated)" audit: "/bin/ps -fC $kubeletbin" @@ -351,41 +334,25 @@ groups: - id: 3.2 text: "DISA Category Code II - Node Security" checks: - - id: V-242391 - text: "The Kubernetes Kubelet must have anonymous authentication disabled." - audit: "ps -ef | grep kubelet | grep -- --anonymous-auth" + + # TODO Verify this, low confidence this will work + # These both don't work. Might need to be a manual check. + - id: V-242393 + text: "Kubernetes Worker Nodes must not have sshd service running. (Automated)" + audit: '/bin/sh -c ''systemctl show -p ActiveState sshd'' ' tests: test_items: - - flag: "--anonymous-auth" + - flag: ActiveState compare: op: eq - value: "false" + value: inactive remediation: | - Edit the Kubernetes Kubelet configuration file. - Set the value of "anonymousAuth" to "false". - Restart the kubelet service using: - systemctl daemon-reload && systemctl restart kubelet - scored: true - - - id: V-242392 - text: "The Kubernetes kubelet must enable explicit authorization." - audit: "ps -ef | grep kubelet | grep -- --authorization-mode" - tests: - test_items: - - flag: "--authorization-mode" - compare: - op: eq - value: "Webhook" - remediation: | - Edit the Kubernetes Kubelet configuration file. - Set the "authorization.mode" to "Webhook". - Restart the kubelet service using: - systemctl daemon-reload && systemctl restart kubelet + To stop the sshd service, run the command: systemctl stop sshd scored: true - id: V-242393 text: "Kubernetes Worker Nodes must not have sshd service running." - audit: "systemctl status sshd" + audit: "/bin/sh -c \"systemctl status sshd\"" tests: test_items: - flag: "sshd" @@ -399,6 +366,18 @@ groups: systemctl disable sshd scored: true + # TODO Verify this, low confidence this will work + # Both of these are not working at the moment + - id: V-242394 + text: "Kubernetes Worker Nodes must not have the sshd service enabled. (Automated)" + audit: "/bin/sh -c 'systemctl is-enabled sshd.service'" + tests: + test_items: + - flag: "disabled" + remediation: | + To disable the sshd service, run the command: + chkconfig sshd off + scored: true - id: V-242394 text: "Kubernetes Worker Nodes must not have the sshd service enabled." audit: "systemctl is-enabled sshd" @@ -413,19 +392,6 @@ groups: systemctl disable sshd scored: true - - id: V-242397 - text: "The Kubernetes kubelet staticPodPath must not enable static pods." - audit: "ps -ef | grep kubelet | grep -- --config" - tests: - test_items: - - flag: "staticPodPath" - set: false - remediation: | - Edit the Kubernetes kubelet configuration file. - Remove the setting "staticPodPath". - Restart the kubelet service using: - systemctl daemon-reload && systemctl restart kubelet - scored: true - id: V-242434 # CIS 3.2.6 text: "Ensure that the --make-iptables-util-chains argument is set to true (Automated)" diff --git a/cfg/gke-stig-kubernetes-v2r2/policies.yaml b/cfg/gke-stig-kubernetes-v2r2/policies.yaml index 0581539..34c59d3 100644 --- a/cfg/gke-stig-kubernetes-v2r2/policies.yaml +++ b/cfg/gke-stig-kubernetes-v2r2/policies.yaml @@ -24,6 +24,7 @@ groups: remediation: | Move any user-managed resources from the default, kube-public and kube-node-lease namespaces, to user namespaces. scored: false + - id: V-242437 text: "Kubernetes must have a pod security policy set." audit: "kubectl get podsecuritypolicy" diff --git a/check/check.go b/check/check.go index 58ce6fb..490ec43 100644 --- a/check/check.go +++ b/check/check.go @@ -23,7 +23,7 @@ import ( "github.com/golang/glog" ) -// NodeType indicates the type of node (master, node). +// NodeType indicates the type of node (master, node, federated, etcd, controlplane, policies, managedservices). type NodeType string // State is the state of a control check. diff --git a/cmd/root.go b/cmd/root.go index c674aeb..bb2d2a6 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -66,8 +66,8 @@ var ( // RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ Use: os.Args[0], - Short: "Run CIS Benchmarks checks against a Kubernetes deployment", - Long: `This tool runs the CIS Kubernetes Benchmark (https://www.cisecurity.org/benchmark/kubernetes/)`, + Short: "Run CIS and STIG Benchmarks checks against a Kubernetes deployment", + Long: `This tool runs the CIS and STIG Kubernetes Benchmark (https://www.cisecurity.org/benchmark/kubernetes/)`, Run: func(cmd *cobra.Command, args []string) { bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformInfo(), viper.GetViper()) if err != nil { diff --git a/docs/controls.md b/docs/controls.md index 8655f31..6de299b 100644 --- a/docs/controls.md +++ b/docs/controls.md @@ -57,7 +57,7 @@ the `controls` components have an id and a text description which are displayed in the `kube-bench` output. `type` specifies what kubernetes node type a `controls` is for. Possible values -for `type` are `master` and `node`. +for `type` are `[master, node, federated, etcd, controlplane, policies, managedservices]`. ## Groups diff --git a/job-gke-stig.yaml b/job-gke-stig.yaml new file mode 100644 index 0000000..8d8fc70 --- /dev/null +++ b/job-gke-stig.yaml @@ -0,0 +1,46 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: kube-bench +spec: + template: + spec: + hostPID: true + containers: + - name: kube-bench + imagePullPolicy: Always + # Push the image to your ECR and then refer to it here + # image: + image: us-docker.pkg.dev/dev-frm-core/dev-frm/kube-bench:gke-stig + # To send findings to AWS Security Hub, refer to `job-eks-asff.yaml` instead + command: + [ + "kube-bench", + "run", + "--benchmark", + "gke-stig-kubernetes-v2r2", + "-v", + "10", + ] + volumeMounts: + - name: var-lib-kubelet + mountPath: /var/lib/kubelet + readOnly: true + - name: etc-systemd + mountPath: /etc/systemd + readOnly: true + - name: etc-kubernetes + mountPath: /etc/kubernetes + readOnly: true + restartPolicy: Never + volumes: + - name: var-lib-kubelet + hostPath: + path: "/var/lib/kubelet" + - name: etc-systemd + hostPath: + path: "/etc/systemd" + - name: etc-kubernetes + hostPath: + path: "/etc/kubernetes"