mirror of
https://github.com/aquasecurity/kube-bench.git
synced 2026-02-24 14:54:27 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20ec5d14f2 | ||
|
|
3e6a41af04 | ||
|
|
1b5b6c2afe | ||
|
|
52ebfa5b5a | ||
|
|
5cf3821eb6 | ||
|
|
c7b518e76b | ||
|
|
122bc4b351 | ||
|
|
35cf28c140 | ||
|
|
2cf2876a10 | ||
|
|
305283f9d4 | ||
|
|
4557ca00f1 | ||
|
|
582ce02ce6 | ||
|
|
82614d9b3f | ||
|
|
d8234ff07c | ||
|
|
7e87c980b2 | ||
|
|
7cd6b32ebb |
@@ -9,6 +9,11 @@ builds:
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
ldflags:
|
||||
- "-X github.com/aquasecurity/kube-bench/cmd.KubeBenchVersion={{.Version}}"
|
||||
- "-X github.com/aquasecurity/kube-bench/cmd.cfgDir={{.Env.KUBEBENCH_CFG}}"
|
||||
@@ -16,6 +21,7 @@ builds:
|
||||
archives:
|
||||
- id: default
|
||||
format: tar.gz
|
||||
name_template: '{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{.Arm }}{{ end }}'
|
||||
files:
|
||||
- "cfg/**/*"
|
||||
nfpms:
|
||||
|
||||
@@ -9,7 +9,7 @@ Thank you for taking an interest in contributing to kube-bench !
|
||||
- For questions and bug reports, please include the following information:
|
||||
- version of kube-bench you are running (from kube-bench version) along with the command line options you are using.
|
||||
- version of Kubernetes you are running (from kubectl version or oc version for Openshift).
|
||||
- Verbose log output, by setting the `-v 10` command line option.
|
||||
- Verbose log output, by setting the `-v 10` and `--logtostderr` command line options.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
|
||||
21
README.md
21
README.md
@@ -10,10 +10,17 @@
|
||||
|
||||
kube-bench is a Go application that checks whether Kubernetes is deployed securely by running the checks documented in the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/).
|
||||
|
||||
Note that it is impossible to inspect the master nodes of managed clusters, e.g. GKE, EKS and AKS, using kube-bench as one does not have access to such nodes, although it is still possible to use kube-bench to check worker node configuration in these environments.
|
||||
|
||||
Tests are configured with YAML files, making this tool easy to update as test specifications evolve.
|
||||
|
||||
### Please Note
|
||||
|
||||
1. kube-bench implements the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/) as closely as possible. Please raise issues here if kube-bench is not correctly implementing the test as described in the Benchmark. To report issues in the Benchmark itself (for example, tests that you believe are inappropriate), please join the [CIS community](https://cisecurity.org).
|
||||
|
||||
1. There is not a one-to-one mapping between releases of Kubernetes and releases of the CIS benchmark. See [CIS Kubernetes Benchmark support](#cis-kubernetes-benchmark-support) to see which releases of Kubernetes are covered by different releases of the benchmark.
|
||||
|
||||
1. It is impossible to inspect the master nodes of managed clusters, e.g. GKE, EKS and AKS, using kube-bench as one does not have access to such nodes, although it is still possible to use kube-bench to check worker node configuration in these environments.
|
||||
|
||||
|
||||

|
||||
|
||||
Table of Contents
|
||||
@@ -51,6 +58,7 @@ kube-bench supports the tests for Kubernetes as defined in the [CIS Kubernetes B
|
||||
| [1.4.1](https://workbench.cisecurity.org/benchmarks/2351) | cis-1.4 | 1.13-1.14 |
|
||||
| [1.5.0](https://workbench.cisecurity.org/benchmarks/1370) | cis-1.5 | 1.15- |
|
||||
| [GKE 1.0.0](https://workbench.cisecurity.org/benchmarks/4536) | gke-1.0 | GKE |
|
||||
| [EKS 1.0.0](https://workbench.cisecurity.org/benchmarks/5190) | eks-1.0 | EKS |
|
||||
| Red Hat OpenShift hardening guide | rh-0.7 | OCP 3.10-3.11 |
|
||||
|
||||
By default, kube-bench will determine the test set to run based on the Kubernetes version running on the machine, but please note that kube-bench does not automatically detect OpenShift and GKE - see the section below on [Running kube-bench](https://github.com/aquasecurity/kube-bench#running-kube-bench).
|
||||
@@ -113,6 +121,7 @@ The following table shows the valid targets based on the CIS Benchmark version.
|
||||
| cis-1.4| master, node |
|
||||
| cis-1.5| master, controlplane, node, etcd, policies |
|
||||
| gke-1.0| master, controlplane, node, etcd, policies, managedservices |
|
||||
| eks-1.0| node, policies, managedservices |
|
||||
|
||||
If no targets are specified, `kube-bench` will determine the appropriate targets based on the CIS Benchmark version.
|
||||
|
||||
@@ -209,7 +218,7 @@ aws ecr create-repository --repository-name k8s/kube-bench --image-tag-mutabilit
|
||||
```
|
||||
git clone https://github.com/aquasecurity/kube-bench.git
|
||||
cd kube-bench
|
||||
$(aws ecr get-login --no-include-email --region <AWS_REGION>)
|
||||
aws ecr get-login-password --region <AWS_REGION> | docker login --username <AWS_USERNAME> --password-stdin <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com
|
||||
docker build -t k8s/kube-bench .
|
||||
docker tag k8s/kube-bench:latest <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest
|
||||
docker push <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest
|
||||
@@ -237,9 +246,7 @@ If Go is installed on the target machines, you can simply clone this repository
|
||||
|
||||
```shell
|
||||
go get github.com/aquasecurity/kube-bench
|
||||
go get github.com/golang/dep/cmd/dep
|
||||
cd $GOPATH/src/github.com/aquasecurity/kube-bench
|
||||
$GOPATH/bin/dep ensure -vendor-only
|
||||
go build -o kube-bench .
|
||||
|
||||
# See all supported options
|
||||
@@ -252,7 +259,7 @@ go build -o kube-bench .
|
||||
## Running on OpenShift
|
||||
|
||||
| OpenShift Hardening Guide | kube-bench config |
|
||||
|---|---|---|
|
||||
|---|---|
|
||||
| ocp-3.10| rh-0.7 |
|
||||
| ocp-3.11| rh-0.7 |
|
||||
|
||||
@@ -314,7 +321,7 @@ No tests will be run for this check and the output will be marked [INFO].
|
||||
|
||||
## Roadmap
|
||||
|
||||
Going forward we plan to release updates to kube-bench to add support for new releases of the Benchmark, which in turn we can anticipate being made for each new Kubernetes release.
|
||||
Going forward we plan to release updates to kube-bench to add support for new releases of the CIS Benchmark. Note that these are not released as frequently as Kubernetes releases.
|
||||
|
||||
We welcome PRs and issue reports.
|
||||
|
||||
|
||||
@@ -456,7 +456,12 @@ groups:
|
||||
|
||||
- id: 2.2.8
|
||||
text: Ensure that the client certificate authorities file ownership is set to root:root (Scored)
|
||||
audit: '/bin/sh -c ''if test -e $kubeletcafile; then stat -c %U:%G $kubeletcafile; fi'' '
|
||||
audit: |
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}')
|
||||
if [[ -z $CAFILE ]]; then
|
||||
CAFILE=$kubeletcafile
|
||||
fi
|
||||
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
@@ -477,7 +482,7 @@ groups:
|
||||
- flag: root:root
|
||||
set: true
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chown root:root $kubeletconf
|
||||
scored: true
|
||||
|
||||
@@ -492,6 +497,6 @@ groups:
|
||||
op: bitmask
|
||||
value: "644"
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chmod 644 $kubeletconf
|
||||
scored: true
|
||||
|
||||
@@ -447,7 +447,12 @@ groups:
|
||||
|
||||
- id: 2.2.8
|
||||
text: Ensure that the client certificate authorities file ownership is set to root:root (Scored)
|
||||
audit: '/bin/sh -c ''if test -e $kubeletcafile; then stat -c %U:%G $kubeletcafile; fi'' '
|
||||
audit: |
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}')
|
||||
if [[ -z $CAFILE ]]; then
|
||||
CAFILE=$kubeletcafile
|
||||
fi
|
||||
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
@@ -468,7 +473,7 @@ groups:
|
||||
- flag: root:root
|
||||
set: true
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chown root:root $kubeletconf
|
||||
scored: true
|
||||
|
||||
@@ -483,6 +488,6 @@ groups:
|
||||
op: bitmask
|
||||
value: "644"
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chmod 644 $kubeletconf
|
||||
scored: true
|
||||
|
||||
@@ -9,7 +9,7 @@ groups:
|
||||
text: "Authentication and Authorization"
|
||||
checks:
|
||||
- id: 3.1.1
|
||||
text: "Client certificate authentication should not be used for users (Not Scored) "
|
||||
text: "Client certificate authentication should not be used for users (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be
|
||||
@@ -20,14 +20,14 @@ groups:
|
||||
text: "Logging"
|
||||
checks:
|
||||
- id: 3.2.1
|
||||
text: "Ensure that a minimal audit policy is created (Scored) "
|
||||
text: "Ensure that a minimal audit policy is created (Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create an audit policy file for your cluster.
|
||||
scored: true
|
||||
|
||||
- id: 3.2.2
|
||||
text: "Ensure that the audit policy covers key security concerns (Not Scored) "
|
||||
text: "Ensure that the audit policy covers key security concerns (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Consider modification of the audit policy in use on the cluster to include these items, at a
|
||||
|
||||
@@ -6,7 +6,7 @@ text: "Master Node Security Configuration"
|
||||
type: "master"
|
||||
groups:
|
||||
- id: 1.1
|
||||
text: "Master Node Configuration Files "
|
||||
text: "Master Node Configuration Files"
|
||||
checks:
|
||||
- id: 1.1.1
|
||||
text: "Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Scored)"
|
||||
@@ -169,7 +169,8 @@ groups:
|
||||
remediation: |
|
||||
On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
|
||||
from the below command:
|
||||
ps -ef | grep etcd Run the below command (based on the etcd data directory found above). For example,
|
||||
ps -ef | grep etcd
|
||||
Run the below command (based on the etcd data directory found above). For example,
|
||||
chmod 700 /var/lib/etcd
|
||||
scored: true
|
||||
|
||||
@@ -205,7 +206,7 @@ groups:
|
||||
scored: true
|
||||
|
||||
- id: 1.1.14
|
||||
text: "Ensure that the admin.conf file ownership is set to root:root (Scored) "
|
||||
text: "Ensure that the admin.conf file ownership is set to root:root (Scored)"
|
||||
audit: "/bin/sh -c 'if test -e /etc/kubernetes/admin.conf; then stat -c %U:%G /etc/kubernetes/admin.conf; fi'"
|
||||
tests:
|
||||
test_items:
|
||||
@@ -295,7 +296,7 @@ groups:
|
||||
scored: true
|
||||
|
||||
- id: 1.1.20
|
||||
text: "Ensure that the Kubernetes PKI certificate file permissions are set to 644 or more restrictive (Scored) "
|
||||
text: "Ensure that the Kubernetes PKI certificate file permissions are set to 644 or more restrictive (Scored)"
|
||||
audit: "stat -c %n\ %a /etc/kubernetes/pki/*.crt"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
@@ -637,7 +638,7 @@ groups:
|
||||
scored: true
|
||||
|
||||
- id: 1.2.20
|
||||
text: "Ensure that the --secure-port argument is not set to 0 (Scored) "
|
||||
text: "Ensure that the --secure-port argument is not set to 0 (Scored)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
bin_op: or
|
||||
@@ -788,7 +789,7 @@ groups:
|
||||
scored: true
|
||||
|
||||
- id: 1.2.29
|
||||
text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored) "
|
||||
text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
bin_op: and
|
||||
@@ -1019,7 +1020,7 @@ groups:
|
||||
scored: true
|
||||
|
||||
- id: 1.4.2
|
||||
text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Scored) "
|
||||
text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Scored)"
|
||||
audit: "/bin/ps -ef | grep $schedulerbin | grep -v grep"
|
||||
tests:
|
||||
bin_op: or
|
||||
|
||||
@@ -107,7 +107,12 @@ groups:
|
||||
|
||||
- id: 4.1.8
|
||||
text: "Ensure that the client certificate authorities file ownership is set to root:root (Scored)"
|
||||
audit: '/bin/sh -c ''if test -e $kubeletcafile; then stat -c %U:%G $kubeletcafile; fi'' '
|
||||
audit: |
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}')
|
||||
if [[ -z $CAFILE ]]; then
|
||||
CAFILE=$kubeletcafile
|
||||
fi
|
||||
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
@@ -131,7 +136,7 @@ groups:
|
||||
op: bitmask
|
||||
value: "644"
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chmod 644 $kubeletconf
|
||||
scored: true
|
||||
|
||||
@@ -143,7 +148,7 @@ groups:
|
||||
- flag: root:root
|
||||
set: true
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chown root:root $kubeletconf
|
||||
scored: true
|
||||
|
||||
@@ -293,7 +298,7 @@ groups:
|
||||
scored: true
|
||||
|
||||
- id: 4.2.7
|
||||
text: "Ensure that the --make-iptables-util-chains argument is set to true (Scored) "
|
||||
text: "Ensure that the --make-iptables-util-chains argument is set to true (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
|
||||
@@ -37,7 +37,7 @@ groups:
|
||||
- id: 5.1.4
|
||||
text: "Minimize access to create pods (Not Scored)"
|
||||
type: "manual"
|
||||
Remediation: |
|
||||
remediation: |
|
||||
Where possible, remove create access to pod objects in the cluster.
|
||||
scored: false
|
||||
|
||||
@@ -128,7 +128,7 @@ groups:
|
||||
scored: false
|
||||
|
||||
- id: 5.2.9
|
||||
text: "Minimize the admission of containers with capabilities assigned (Not Scored) "
|
||||
text: "Minimize the admission of containers with capabilities assigned (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Review the use of capabilites in applications runnning on your cluster. Where a namespace
|
||||
|
||||
2
cfg/eks-1.0/config.yaml
Normal file
2
cfg/eks-1.0/config.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
14
cfg/eks-1.0/controlplane.yaml
Normal file
14
cfg/eks-1.0/controlplane.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.0"
|
||||
id: 2
|
||||
text: "Control Plane Configuration"
|
||||
type: "controlplane"
|
||||
groups:
|
||||
- id: 2.1
|
||||
text: "Logging"
|
||||
checks:
|
||||
- id: 2.1.1
|
||||
text: "Enable audit logs"
|
||||
remediation: "Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler."
|
||||
scored: false
|
||||
104
cfg/eks-1.0/managedservices.yaml
Normal file
104
cfg/eks-1.0/managedservices.yaml
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.0"
|
||||
id: 5
|
||||
text: "Managed Services"
|
||||
type: "managedservices"
|
||||
groups:
|
||||
- id: 5.1
|
||||
text: "Image Registry and Image Scanning"
|
||||
checks:
|
||||
- id: 5.1.1
|
||||
text: "Ensure Image Vulnerability Scanning using Amazon ECR image scanning or a third-party provider (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.1.2
|
||||
text: "Minimize user access to Amazon ECR (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.1.3
|
||||
text: "Minimize cluster access to read-only for Amazon ECR (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.1.4
|
||||
text: "Minimize Container Registries to only those approved (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.2
|
||||
text: "Identity and Access Management (IAM)"
|
||||
checks:
|
||||
- id: 5.2.1
|
||||
text: "Prefer using dedicated Amazon EKS Service Accounts (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.3
|
||||
text: "AWS Key Management Service (AWS KMS)"
|
||||
checks:
|
||||
- id: 5.3.1
|
||||
text: "Ensure Kubernetes Secrets are encrypted using Customer Master Keys (CMKs) managed in AWS KMS (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.4
|
||||
text: "Cluster Networking"
|
||||
checks:
|
||||
- id: 5.4.1
|
||||
text: "Restrict Access to the Control Plane Endpoint (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.4.2
|
||||
text: "Ensure clusters are created with Private Endpoint Enabled and Public Access Disabled (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.4.3
|
||||
text: "Ensure clusters are created with Private Nodes (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.4.4
|
||||
text: "Ensure Network Policy is Enabled and set as appropriate (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
- id: 5.4.5
|
||||
text: "Encrypt traffic to HTTPS load balancers with TLS certificates (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
|
||||
- id: 5.5
|
||||
text: "Authentication and Authorization"
|
||||
checks:
|
||||
- id: 5.5.1
|
||||
text: "Manage Kubernetes RBAC users with AWS IAM Authenticator for Kubernetes (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
|
||||
|
||||
- id: 5.6
|
||||
text: "Other Cluster Configurations"
|
||||
checks:
|
||||
- id: 5.6.1
|
||||
text: "Consider Fargate for running untrusted workloads (Not Scored)"
|
||||
type: "manual"
|
||||
remediation:
|
||||
scored: false
|
||||
6
cfg/eks-1.0/master.yaml
Normal file
6
cfg/eks-1.0/master.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.0"
|
||||
id: 1
|
||||
text: "Control Plane Components"
|
||||
type: "master"
|
||||
388
cfg/eks-1.0/node.yaml
Normal file
388
cfg/eks-1.0/node.yaml
Normal file
@@ -0,0 +1,388 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.0"
|
||||
id: 3
|
||||
text: "Worker Node Security Configuration"
|
||||
type: "node"
|
||||
groups:
|
||||
- id: 3.1
|
||||
text: "Worker Node Configuration Files"
|
||||
checks:
|
||||
- id: 3.1.1
|
||||
text: "Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)"
|
||||
audit: '/bin/sh -c ''if test -e $proxykubeconfig; then stat -c %a $proxykubeconfig; fi'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "644"
|
||||
compare:
|
||||
op: eq
|
||||
value: "644"
|
||||
set: true
|
||||
- flag: "640"
|
||||
compare:
|
||||
op: eq
|
||||
value: "640"
|
||||
set: true
|
||||
- flag: "600"
|
||||
compare:
|
||||
op: eq
|
||||
value: "600"
|
||||
set: true
|
||||
- flag: "444"
|
||||
compare:
|
||||
op: eq
|
||||
value: "444"
|
||||
set: true
|
||||
- flag: "440"
|
||||
compare:
|
||||
op: eq
|
||||
value: "440"
|
||||
set: true
|
||||
- flag: "400"
|
||||
compare:
|
||||
op: eq
|
||||
value: "400"
|
||||
set: true
|
||||
- flag: "000"
|
||||
compare:
|
||||
op: eq
|
||||
value: "000"
|
||||
set: true
|
||||
bin_op: or
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on each worker node.
|
||||
For example,
|
||||
chmod 644 $proykubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 3.1.2
|
||||
text: "Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)"
|
||||
audit: '/bin/sh -c ''if test -e $proxykubeconfig; then stat -c %U:%G $proxykubeconfig; fi'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
set: true
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on each worker node.
|
||||
For example, chown root:root $proxykubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 3.1.3
|
||||
text: "Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)"
|
||||
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c %a $kubeletconf; fi'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "644"
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: "644"
|
||||
- flag: "640"
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: "640"
|
||||
- flag: "600"
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: "600"
|
||||
- flag: "444"
|
||||
compare:
|
||||
op: eq
|
||||
value: "444"
|
||||
set: true
|
||||
- flag: "440"
|
||||
compare:
|
||||
op: eq
|
||||
value: "440"
|
||||
set: true
|
||||
- flag: "400"
|
||||
compare:
|
||||
op: eq
|
||||
value: "400"
|
||||
set: true
|
||||
- flag: "000"
|
||||
compare:
|
||||
op: eq
|
||||
value: "000"
|
||||
set: true
|
||||
bin_op: or
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
chmod 644 $kubeletconf
|
||||
scored: true
|
||||
|
||||
- id: 3.1.4
|
||||
text: "Ensure that the kubelet configuration file ownership is set to root:root (Scored)"
|
||||
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c %U:%G $kubeletconf; fi'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
set: true
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
chown root:root $kubeletconf
|
||||
scored: true
|
||||
|
||||
- id: 3.2
|
||||
text: "Kubelet"
|
||||
checks:
|
||||
- id: 3.2.1
|
||||
text: "Ensure that the --anonymous-auth argument is set to false (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
path: '{.authentication.anonymous.enabled}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set authentication: anonymous: enabled to
|
||||
false.
|
||||
If using executable arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--anonymous-auth=false
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.2
|
||||
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --authorization-mode
|
||||
path: '{.authorization.mode}'
|
||||
set: true
|
||||
compare:
|
||||
op: nothave
|
||||
value: AlwaysAllow
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set authorization: mode to Webhook. If
|
||||
using executable arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
set the below parameter in KUBELET_AUTHZ_ARGS variable.
|
||||
--authorization-mode=Webhook
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.3
|
||||
text: "Ensure that the --client-ca-file argument is set as appropriate (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --client-ca-file
|
||||
path: '{.authentication.x509.clientCAFile}'
|
||||
set: true
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set authentication: x509: clientCAFile to
|
||||
the location of the client CA file.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
set the below parameter in KUBELET_AUTHZ_ARGS variable.
|
||||
--client-ca-file=<path/to/client-ca-file>
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.4
|
||||
text: "Ensure that the --read-only-port argument is set to 0 (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--read-only-port"
|
||||
path: '{.readOnlyPort}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: 0
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set readOnlyPort to 0.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--read-only-port=0
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.5
|
||||
text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --streaming-connection-idle-timeout
|
||||
path: '{.streamingConnectionIdleTimeout}'
|
||||
set: true
|
||||
compare:
|
||||
op: noteq
|
||||
value: 0
|
||||
- flag: --streaming-connection-idle-timeout
|
||||
path: '{.streamingConnectionIdleTimeout}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set streamingConnectionIdleTimeout to a
|
||||
value other than 0.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--streaming-connection-idle-timeout=5m
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.6
|
||||
text: "Ensure that the --protect-kernel-defaults argument is set to true (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --protect-kernel-defaults
|
||||
path: '{.protectKernelDefaults}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set protectKernelDefaults: true.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--protect-kernel-defaults=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.7
|
||||
text: "Ensure that the --make-iptables-util-chains argument is set to true (Scored) "
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --make-iptables-util-chains
|
||||
path: '{.makeIPTablesUtilChains}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --make-iptables-util-chains
|
||||
path: '{.makeIPTablesUtilChains}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set makeIPTablesUtilChains: true.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
remove the --make-iptables-util-chains argument from the
|
||||
KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.8
|
||||
text: "Ensure that the --hostname-override argument is not set (Scored)"
|
||||
# This is one of those properties that can only be set as a command line argument.
|
||||
# To check if the property is set as expected, we need to parse the kubelet command
|
||||
# instead reading the Kubelet Configuration file.
|
||||
audit: "/bin/ps -fC $kubeletbin "
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --hostname-override
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and remove the --hostname-override argument from the
|
||||
KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.9
|
||||
text: "Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --event-qps
|
||||
path: '{.eventRecordQPS}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: 0
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set eventRecordQPS: to an appropriate level.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
|
||||
- id: 3.2.10
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to add the line rotateCertificates: true or
|
||||
remove it altogether to use the default value.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
remove --rotate-certificates=false argument from the KUBELET_CERTIFICATE_ARGS
|
||||
variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 3.2.11
|
||||
text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
237
cfg/eks-1.0/policies.yaml
Normal file
237
cfg/eks-1.0/policies.yaml
Normal file
@@ -0,0 +1,237 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.0"
|
||||
id: 4
|
||||
text: "Policies"
|
||||
type: "policies"
|
||||
groups:
|
||||
- id: 4.1
|
||||
text: "RBAC and Service Accounts"
|
||||
checks:
|
||||
- id: 4.1.1
|
||||
text: "Ensure that the cluster-admin role is only used where required (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Identify all clusterrolebindings to the cluster-admin role. Check if they are used and
|
||||
if they need this role or if they could use a role with fewer privileges.
|
||||
Where possible, first bind users to a lower privileged role and then remove the
|
||||
clusterrolebinding to the cluster-admin role :
|
||||
kubectl delete clusterrolebinding [name]
|
||||
scored: false
|
||||
|
||||
- id: 4.1.2
|
||||
text: "Minimize access to secrets (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove get, list and watch access to secret objects in the cluster.
|
||||
scored: false
|
||||
|
||||
- id: 4.1.3
|
||||
text: "Minimize wildcard use in Roles and ClusterRoles (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible replace any use of wildcards in clusterroles and roles with specific
|
||||
objects or actions.
|
||||
scored: false
|
||||
|
||||
- id: 4.1.4
|
||||
text: "Minimize access to create pods (Not Scored)"
|
||||
type: "manual"
|
||||
Remediation: |
|
||||
Where possible, remove create access to pod objects in the cluster.
|
||||
scored: false
|
||||
|
||||
- id: 4.1.5
|
||||
text: "Ensure that default service accounts are not actively used. (Not Scored)"
|
||||
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: 4.1.6
|
||||
text: "Ensure that Service Account Tokens are only mounted where necessary (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Modify the definition of pods and service accounts which do not need to mount service
|
||||
account tokens to disable it.
|
||||
scored: false
|
||||
|
||||
- id: 4.2
|
||||
text: "Pod Security Policies"
|
||||
checks:
|
||||
- id: 4.2.1
|
||||
text: "Minimize the admission of privileged containers (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that
|
||||
the .spec.privileged field is omitted or set to false.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.2
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostPID field is omitted or set to false.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostIPC field is omitted or set to false.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostNetwork field is omitted or set to false.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.5
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.allowPrivilegeEscalation field is omitted or set to false.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.6
|
||||
text: "Minimize the admission of root containers (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.runAsUser.rule is set to either MustRunAsNonRoot or MustRunAs with the range of
|
||||
UIDs not including 0.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.7
|
||||
text: "Minimize the admission of containers with the NET_RAW capability (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.requiredDropCapabilities is set to include either NET_RAW or ALL.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.8
|
||||
text: "Minimize the admission of containers with added capabilities (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that allowedCapabilities is not present in PSPs for the cluster unless
|
||||
it is set to an empty array.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.9
|
||||
text: "Minimize the admission of containers with capabilities assigned (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Review the use of capabilites in applications runnning on your cluster. Where a namespace
|
||||
contains applications which do not require any Linux capabities to operate consider adding
|
||||
a PSP which forbids the admission of containers which do not drop all capabilities.
|
||||
scored: false
|
||||
|
||||
- id: 4.3
|
||||
text: "CNI Plugin"
|
||||
checks:
|
||||
- id: 4.3.1
|
||||
text: "Ensure that the latest CNI version is used (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Review the documentation of AWS CNI plugin, and ensure latest CNI version is used.
|
||||
scored: false
|
||||
|
||||
- id: 4.3.2
|
||||
text: "Ensure that all Namespaces have Network Policies defined (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the documentation and create NetworkPolicy objects as you need them.
|
||||
scored: false
|
||||
|
||||
- id: 4.4
|
||||
text: "Secrets Management"
|
||||
checks:
|
||||
- id: 4.4.1
|
||||
text: "Prefer using secrets as files over secrets as environment variables (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
If possible, rewrite application code to read secrets from mounted secret files, rather than
|
||||
from environment variables.
|
||||
scored: false
|
||||
|
||||
- id: 4.4.2
|
||||
text: "Consider external secret storage (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Refer to the secrets management options offered by your cloud provider or a third-party
|
||||
secrets management solution.
|
||||
scored: false
|
||||
|
||||
- id: 4.5
|
||||
text: "Extensible Admission Control"
|
||||
checks:
|
||||
- id: 4.5.1
|
||||
text: "Configure Image Provenance using ImagePolicyWebhook admission controller (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and setup image provenance.
|
||||
scored: false
|
||||
|
||||
- id: 4.6
|
||||
text: "General Policies"
|
||||
checks:
|
||||
- id: 4.6.1
|
||||
text: "Create administrative boundaries between resources using namespaces (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the documentation and create namespaces for objects in your deployment as you need
|
||||
them.
|
||||
scored: false
|
||||
|
||||
- id: 4.6.2
|
||||
text: "Ensure that the seccomp profile is set to docker/default in your pod definitions (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Seccomp is an alpha feature currently. By default, all alpha features are disabled. So, you
|
||||
would need to enable alpha features in the apiserver by passing "--feature-
|
||||
gates=AllAlpha=true" argument.
|
||||
Edit the /etc/kubernetes/apiserver file on the master node and set the KUBE_API_ARGS
|
||||
parameter to "--feature-gates=AllAlpha=true"
|
||||
KUBE_API_ARGS="--feature-gates=AllAlpha=true"
|
||||
Based on your system, restart the kube-apiserver service. For example:
|
||||
systemctl restart kube-apiserver.service
|
||||
Use annotations to enable the docker/default seccomp profile in your pod definitions. An
|
||||
example is as below:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: trustworthy-pod
|
||||
annotations:
|
||||
seccomp.security.alpha.kubernetes.io/pod: docker/default
|
||||
spec:
|
||||
containers:
|
||||
- name: trustworthy-container
|
||||
image: sotrustworthy:latest
|
||||
scored: false
|
||||
|
||||
- id: 4.6.3
|
||||
text: "Apply Security Context to Your Pods and Containers (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and apply security contexts to your pods. For a
|
||||
suggested list of security contexts, you may refer to the CIS Security Benchmark for Docker
|
||||
Containers.
|
||||
scored: false
|
||||
|
||||
- id: 4.6.4
|
||||
text: "The default namespace should not be used (Not Scored)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
|
||||
resources and that all new resources are created in a specific namespace.
|
||||
scored: false
|
||||
@@ -139,7 +139,7 @@ groups:
|
||||
set: true
|
||||
bin_op: or
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chmod 644 $kubeletconf
|
||||
scored: true
|
||||
|
||||
@@ -151,7 +151,7 @@ groups:
|
||||
- flag: root:root
|
||||
set: true
|
||||
remediation: |
|
||||
Run the following command (using the config file location identied in the Audit step)
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chown root:root $kubeletconf
|
||||
scored: true
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ groups:
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Review the use of capabilites in applications runnning on your cluster. Where a namespace
|
||||
contains applicaions which do not require any Linux capabities to operate consider adding
|
||||
contains applications which do not require any Linux capabities to operate consider adding
|
||||
a PSP which forbids the admission of containers which do not drop all capabilities.
|
||||
scored: true
|
||||
|
||||
|
||||
172
check/check.go
172
check/check.go
@@ -17,10 +17,7 @@ package check
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
@@ -65,22 +62,20 @@ const (
|
||||
// Check contains information about a recommendation in the
|
||||
// CIS Kubernetes document.
|
||||
type Check struct {
|
||||
ID string `yaml:"id" json:"test_number"`
|
||||
Text string `json:"test_desc"`
|
||||
Audit string `json:"audit"`
|
||||
AuditConfig string `yaml:"audit_config"`
|
||||
Type string `json:"type"`
|
||||
Commands []*exec.Cmd `json:"omit"`
|
||||
ConfigCommands []*exec.Cmd `json:"omit"`
|
||||
Tests *tests `json:"omit"`
|
||||
Set bool `json:"omit"`
|
||||
Remediation string `json:"remediation"`
|
||||
TestInfo []string `json:"test_info"`
|
||||
ID string `yaml:"id" json:"test_number"`
|
||||
Text string `json:"test_desc"`
|
||||
Audit string `json:"audit"`
|
||||
AuditConfig string `yaml:"audit_config"`
|
||||
Type string `json:"type"`
|
||||
Tests *tests `json:"omit"`
|
||||
Set bool `json:"omit"`
|
||||
Remediation string `json:"remediation"`
|
||||
TestInfo []string `json:"test_info"`
|
||||
State `json:"status"`
|
||||
ActualValue string `json:"actual_value"`
|
||||
Scored bool `json:"scored"`
|
||||
ExpectedResult string `json:"expected_result"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
}
|
||||
|
||||
// Runner wraps the basic Run method.
|
||||
@@ -128,9 +123,9 @@ func (c *Check) run() State {
|
||||
}
|
||||
|
||||
lastCommand := c.Audit
|
||||
hasAuditConfig := c.ConfigCommands != nil
|
||||
hasAuditConfig := c.AuditConfig != ""
|
||||
|
||||
state, finalOutput, retErrmsgs := performTest(c.Audit, c.Commands, c.Tests)
|
||||
state, finalOutput, retErrmsgs := performTest(c.Audit, c.Tests)
|
||||
if len(state) > 0 {
|
||||
c.Reason = retErrmsgs
|
||||
c.State = state
|
||||
@@ -166,7 +161,7 @@ func (c *Check) run() State {
|
||||
currentTests.TestItems[i] = nti
|
||||
}
|
||||
|
||||
state, finalOutput, retErrmsgs = performTest(c.AuditConfig, c.ConfigCommands, currentTests)
|
||||
state, finalOutput, retErrmsgs = performTest(c.AuditConfig, currentTests)
|
||||
if len(state) > 0 {
|
||||
c.Reason = retErrmsgs
|
||||
c.State = state
|
||||
@@ -200,78 +195,13 @@ func (c *Check) run() State {
|
||||
return c.State
|
||||
}
|
||||
|
||||
// textToCommand transforms an input text representation of commands to be
|
||||
// run into a slice of commands.
|
||||
// TODO: Make this more robust.
|
||||
func textToCommand(s string) []*exec.Cmd {
|
||||
glog.V(3).Infof("textToCommand: %q\n", s)
|
||||
cmds := []*exec.Cmd{}
|
||||
|
||||
cp := strings.Split(s, "|")
|
||||
|
||||
for _, v := range cp {
|
||||
v = strings.Trim(v, " ")
|
||||
|
||||
// TODO:
|
||||
// GOAL: To split input text into arguments for exec.Cmd.
|
||||
//
|
||||
// CHALLENGE: The input text may contain quoted strings that
|
||||
// must be passed as a unit to exec.Cmd.
|
||||
// eg. bash -c 'foo bar'
|
||||
// 'foo bar' must be passed as unit to exec.Cmd if not the command
|
||||
// will fail when it is executed.
|
||||
// eg. exec.Cmd("bash", "-c", "foo bar")
|
||||
//
|
||||
// PROBLEM: Current solution assumes the grouped string will always
|
||||
// be at the end of the input text.
|
||||
re := regexp.MustCompile(`^(.*)(['"].*['"])$`)
|
||||
grps := re.FindStringSubmatch(v)
|
||||
|
||||
var cs []string
|
||||
if len(grps) > 0 {
|
||||
s := strings.Trim(grps[1], " ")
|
||||
cs = strings.Split(s, " ")
|
||||
|
||||
s1 := grps[len(grps)-1]
|
||||
s1 = strings.Trim(s1, "'\"")
|
||||
|
||||
cs = append(cs, s1)
|
||||
} else {
|
||||
cs = strings.Split(v, " ")
|
||||
}
|
||||
|
||||
cmd := exec.Command(cs[0], cs[1:]...)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
||||
func isShellCommand(s string) bool {
|
||||
cmd := exec.Command("/bin/sh", "-c", "command -v "+s)
|
||||
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("failed to check if command: %q is valid %v", s, err))
|
||||
}
|
||||
|
||||
if strings.Contains(string(out), s) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func performTest(audit string, commands []*exec.Cmd, tests *tests) (State, *testOutput, string) {
|
||||
func performTest(audit string, tests *tests) (State, *testOutput, string) {
|
||||
if len(strings.TrimSpace(audit)) == 0 {
|
||||
return "", failTestItem("missing command"), "missing audit command"
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
state, retErrmsgs := runExecCommands(audit, commands, &out)
|
||||
if len(state) > 0 {
|
||||
return state, nil, retErrmsgs
|
||||
}
|
||||
errmsgs := retErrmsgs
|
||||
errmsgs := runAudit(audit, &out)
|
||||
|
||||
finalOutput := tests.execute(out.String())
|
||||
if finalOutput == nil {
|
||||
@@ -281,73 +211,17 @@ func performTest(audit string, commands []*exec.Cmd, tests *tests) (State, *test
|
||||
return "", finalOutput, errmsgs
|
||||
}
|
||||
|
||||
func runExecCommands(audit string, commands []*exec.Cmd, out *bytes.Buffer) (State, string) {
|
||||
var err error
|
||||
func runAudit(audit string, out *bytes.Buffer) string {
|
||||
errmsgs := ""
|
||||
|
||||
// Check if command exists or exit with WARN.
|
||||
for _, cmd := range commands {
|
||||
if !isShellCommand(cmd.Path) {
|
||||
errmsgs += fmt.Sprintf("Command '%s' not found\n", cmd.Path)
|
||||
return WARN, errmsgs
|
||||
}
|
||||
}
|
||||
|
||||
// Run commands.
|
||||
n := len(commands)
|
||||
if n == 0 {
|
||||
// Likely a warning message.
|
||||
return WARN, errmsgs
|
||||
}
|
||||
|
||||
// Each command runs,
|
||||
// cmd0 out -> cmd1 in, cmd1 out -> cmd2 in ... cmdn out -> os.stdout
|
||||
// cmd0 err should terminate chain
|
||||
cs := commands
|
||||
|
||||
// Initialize command pipeline
|
||||
cs[n-1].Stdout = out
|
||||
i := 1
|
||||
|
||||
for i < n {
|
||||
cs[i-1].Stdout, err = cs[i].StdinPipe()
|
||||
if err != nil {
|
||||
errmsgs += fmt.Sprintf("failed to run: %s, command: %s, error: %s\n", audit, cs[i].Args, err)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
// Start command pipeline
|
||||
i = 0
|
||||
for i < n {
|
||||
err := cs[i].Start()
|
||||
if err != nil {
|
||||
errmsgs += fmt.Sprintf("failed to run: %s, command: %s, error: %s\n", audit, cs[i].Args, err)
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
// Complete command pipeline
|
||||
i = 0
|
||||
for i < n {
|
||||
err := cs[i].Wait()
|
||||
if err != nil {
|
||||
errmsgs += fmt.Sprintf("failed to run: %s, command: %s, error: %s\n", audit, cs[i].Args, err)
|
||||
}
|
||||
|
||||
if i < n-1 {
|
||||
cs[i].Stdout.(io.Closer).Close()
|
||||
}
|
||||
i++
|
||||
cmd := exec.Command("/bin/sh")
|
||||
cmd.Stdin = strings.NewReader(audit)
|
||||
cmd.Stdout = out
|
||||
cmd.Stderr = out
|
||||
if err := cmd.Run(); err != nil {
|
||||
errmsgs += fmt.Sprintf("failed to run: %q, output: %q, error: %s\n", audit, out.String(), err)
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Command %q - Output:\n\n %q\n - Error Messages:%q \n", audit, out.String(), errmsgs)
|
||||
return "", errmsgs
|
||||
}
|
||||
|
||||
func exitWithError(err error) {
|
||||
fmt.Fprintf(os.Stderr, "\n%v\n", err)
|
||||
// flush before exit non-zero
|
||||
glog.Flush()
|
||||
os.Exit(1)
|
||||
return errmsgs
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -33,8 +34,8 @@ func TestCheck_Run(t *testing.T) {
|
||||
{
|
||||
check: Check{ // Not scored checks with passing tests are marked pass
|
||||
Scored: false,
|
||||
Audit: ":", Commands: []*exec.Cmd{exec.Command("")},
|
||||
Tests: &tests{TestItems: []*testItem{&testItem{}}},
|
||||
Audit: ":",
|
||||
Tests: &tests{TestItems: []*testItem{&testItem{}}},
|
||||
},
|
||||
Expected: PASS,
|
||||
},
|
||||
@@ -44,8 +45,8 @@ func TestCheck_Run(t *testing.T) {
|
||||
{
|
||||
check: Check{ // Scored checks with passing tests are marked pass
|
||||
Scored: true,
|
||||
Audit: ":", Commands: []*exec.Cmd{exec.Command("")},
|
||||
Tests: &tests{TestItems: []*testItem{&testItem{}}},
|
||||
Audit: ":",
|
||||
Tests: &tests{TestItems: []*testItem{&testItem{}}},
|
||||
},
|
||||
Expected: PASS,
|
||||
},
|
||||
@@ -111,3 +112,66 @@ func TestCheckAuditConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_runAudit(t *testing.T) {
|
||||
type args struct {
|
||||
audit string
|
||||
out *bytes.Buffer
|
||||
output string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
errMsg string
|
||||
output string
|
||||
}{
|
||||
{
|
||||
name: "run success",
|
||||
args: args{
|
||||
audit: "echo 'hello world'",
|
||||
out: &bytes.Buffer{},
|
||||
},
|
||||
errMsg: "",
|
||||
output: "hello world\n",
|
||||
},
|
||||
{
|
||||
name: "run multiple lines script",
|
||||
args: args{
|
||||
audit: `
|
||||
hello() {
|
||||
echo "hello world"
|
||||
}
|
||||
|
||||
hello
|
||||
`,
|
||||
out: &bytes.Buffer{},
|
||||
},
|
||||
errMsg: "",
|
||||
output: "hello world\n",
|
||||
},
|
||||
{
|
||||
name: "run failed",
|
||||
args: args{
|
||||
audit: "unknown_command",
|
||||
out: &bytes.Buffer{},
|
||||
},
|
||||
errMsg: "failed to run: \"unknown_command\", output: \"/bin/sh: ",
|
||||
output: "not found\n",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
errMsg := runAudit(tt.args.audit, tt.args.out)
|
||||
if errMsg != "" && !strings.Contains(errMsg, tt.errMsg) {
|
||||
t.Errorf("runAudit() errMsg = %q, want %q", errMsg, tt.errMsg)
|
||||
}
|
||||
output := tt.args.out.String()
|
||||
if errMsg == "" && output != tt.output {
|
||||
t.Errorf("runAudit() output = %q, want %q", output, tt.output)
|
||||
}
|
||||
if errMsg != "" && !strings.Contains(output, tt.output) {
|
||||
t.Errorf("runAudit() output = %q, want %q", output, tt.output)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,18 +70,6 @@ func NewControls(t NodeType, in []byte) (*Controls, error) {
|
||||
return nil, fmt.Errorf("non-%s controls file specified", t)
|
||||
}
|
||||
|
||||
// Prepare audit commands
|
||||
for _, group := range c.Groups {
|
||||
for _, check := range group.Checks {
|
||||
glog.V(3).Infof("Check.ID %s", check.ID)
|
||||
check.Commands = textToCommand(check.Audit)
|
||||
if len(check.AuditConfig) > 0 {
|
||||
glog.V(3).Infof("Check.ID has audit_config %s", check.ID)
|
||||
check.ConfigCommands = textToCommand(check.AuditConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
"k8s.io/client-go/util/jsonpath"
|
||||
)
|
||||
@@ -123,8 +124,8 @@ func (t *testItem) execute(s string) *testOutput {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "invalid flag in testitem definition")
|
||||
os.Exit(1)
|
||||
glog.V(1).Infof(fmt.Sprintf("invalid flag in testitem definition"))
|
||||
return failTestItem("error invalid flag in testitem definition")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,8 +171,8 @@ func compareOp(tCompareOp string, flagVal string, tCompareValue string) (string,
|
||||
case "gt", "gte", "lt", "lte":
|
||||
a, b, err := toNumeric(flagVal, tCompareValue)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Not numeric value - flag: %q - compareValue: %q %v\n", flagVal, tCompareValue, err)
|
||||
os.Exit(1)
|
||||
glog.V(1).Infof(fmt.Sprintf("Not numeric value - flag: %q - compareValue: %q %v\n", flagVal, tCompareValue, err))
|
||||
return "Invalid Number(s) used for comparison", false
|
||||
}
|
||||
switch tCompareOp {
|
||||
case "gt":
|
||||
@@ -213,10 +214,14 @@ func compareOp(tCompareOp string, flagVal string, tCompareValue string) (string,
|
||||
case "bitmask":
|
||||
expectedResultPattern = "bitmask '%s' AND '%s'"
|
||||
requested, err := strconv.ParseInt(flagVal, 8, 64)
|
||||
if err != nil {
|
||||
glog.V(1).Infof(fmt.Sprintf("Not numeric value - flag: %q - compareValue: %q %v\n", flagVal, tCompareValue, err))
|
||||
return fmt.Sprintf("Not numeric value - flag: %s", flagVal), false
|
||||
}
|
||||
max, err := strconv.ParseInt(tCompareValue, 8, 64)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Not numeric value - flag: %q - compareValue: %q %v\n", flagVal, tCompareValue, err)
|
||||
os.Exit(1)
|
||||
glog.V(1).Infof(fmt.Sprintf("Not numeric value - flag: %q - compareValue: %q %v\n", flagVal, tCompareValue, err))
|
||||
return fmt.Sprintf("Not numeric value - flag: %s", tCompareValue), false
|
||||
}
|
||||
testResult = (max & requested) == requested
|
||||
}
|
||||
@@ -330,8 +335,9 @@ func (ts *tests) execute(s string) *testOutput {
|
||||
// If no binary operation is specified, default to AND
|
||||
switch ts.BinOp {
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unknown binary operator for tests %s\n", ts.BinOp)
|
||||
os.Exit(1)
|
||||
glog.V(2).Info(fmt.Sprintf("unknown binary operator for tests %s\n", ts.BinOp))
|
||||
finalOutput.actualResult = fmt.Sprintf("unknown binary operator for tests %s\n", ts.BinOp)
|
||||
return finalOutput
|
||||
case and, "":
|
||||
result = true
|
||||
for i := range res {
|
||||
|
||||
@@ -531,11 +531,9 @@ func TestCompareOp(t *testing.T) {
|
||||
testResult: true},
|
||||
|
||||
// Test Op "gt"
|
||||
// TODO: test for non-numeric values.
|
||||
// toNumeric function currently uses os.Exit, which stops tests.
|
||||
// {label: "op=gt, both empty", op: "gt", flagVal: "",
|
||||
// compareValue: "", expectedResultPattern: "'' is greater than ''",
|
||||
// testResult: true},
|
||||
{label: "op=gt, both empty", op: "gt", flagVal: "",
|
||||
compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=gt, 0 > 0", op: "gt", flagVal: "0",
|
||||
compareValue: "0", expectedResultPattern: "0 is greater than 0",
|
||||
testResult: false},
|
||||
@@ -548,109 +546,124 @@ func TestCompareOp(t *testing.T) {
|
||||
{label: "op=gt, 5 > 5", op: "gt", flagVal: "5",
|
||||
compareValue: "5", expectedResultPattern: "5 is greater than 5",
|
||||
testResult: false},
|
||||
|
||||
{label: "op=gt, Pikachu > 5", op: "gt", flagVal: "Pikachu",
|
||||
compareValue: "5", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=gt, 5 > Bulbasaur", op: "gt", flagVal: "5",
|
||||
compareValue: "Bulbasaur", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
// Test Op "lt"
|
||||
// TODO: test for non-numeric values.
|
||||
// toNumeric function currently uses os.Exit, which stops tests.
|
||||
// {label: "op=lt, both empty", op: "lt", flagVal: "",
|
||||
// compareValue: "", expectedResultPattern: "'' is lower than ''",
|
||||
// testResult: true},
|
||||
{label: "op=gt, 0 < 0", op: "lt", flagVal: "0",
|
||||
{label: "op=lt, both empty", op: "lt", flagVal: "",
|
||||
compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=lt, 0 < 0", op: "lt", flagVal: "0",
|
||||
compareValue: "0", expectedResultPattern: "0 is lower than 0",
|
||||
testResult: false},
|
||||
{label: "op=gt, 4 < 5", op: "lt", flagVal: "4",
|
||||
{label: "op=lt, 4 < 5", op: "lt", flagVal: "4",
|
||||
compareValue: "5", expectedResultPattern: "4 is lower than 5",
|
||||
testResult: true},
|
||||
{label: "op=gt, 5 < 4", op: "lt", flagVal: "5",
|
||||
{label: "op=lt, 5 < 4", op: "lt", flagVal: "5",
|
||||
compareValue: "4", expectedResultPattern: "5 is lower than 4",
|
||||
testResult: false},
|
||||
{label: "op=gt, 5 < 5", op: "lt", flagVal: "5",
|
||||
{label: "op=lt, 5 < 5", op: "lt", flagVal: "5",
|
||||
compareValue: "5", expectedResultPattern: "5 is lower than 5",
|
||||
testResult: false},
|
||||
|
||||
{label: "op=lt, Charmander < 5", op: "lt", flagVal: "Charmander",
|
||||
compareValue: "5", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=lt, 5 < Charmeleon", op: "lt", flagVal: "5",
|
||||
compareValue: "Charmeleon", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
// Test Op "gte"
|
||||
// TODO: test for non-numeric values.
|
||||
// toNumeric function currently uses os.Exit, which stops tests.
|
||||
// {label: "op=gt, both empty", op: "gte", flagVal: "",
|
||||
// compareValue: "", expectedResultPattern: "'' is greater or equal to ''",
|
||||
// testResult: true},
|
||||
{label: "op=gt, 0 >= 0", op: "gte", flagVal: "0",
|
||||
{label: "op=gte, both empty", op: "gte", flagVal: "",
|
||||
compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=gte, 0 >= 0", op: "gte", flagVal: "0",
|
||||
compareValue: "0", expectedResultPattern: "0 is greater or equal to 0",
|
||||
testResult: true},
|
||||
{label: "op=gt, 4 >= 5", op: "gte", flagVal: "4",
|
||||
{label: "op=gte, 4 >= 5", op: "gte", flagVal: "4",
|
||||
compareValue: "5", expectedResultPattern: "4 is greater or equal to 5",
|
||||
testResult: false},
|
||||
{label: "op=gt, 5 >= 4", op: "gte", flagVal: "5",
|
||||
{label: "op=gte, 5 >= 4", op: "gte", flagVal: "5",
|
||||
compareValue: "4", expectedResultPattern: "5 is greater or equal to 4",
|
||||
testResult: true},
|
||||
{label: "op=gt, 5 >= 5", op: "gte", flagVal: "5",
|
||||
{label: "op=gte, 5 >= 5", op: "gte", flagVal: "5",
|
||||
compareValue: "5", expectedResultPattern: "5 is greater or equal to 5",
|
||||
testResult: true},
|
||||
|
||||
{label: "op=gte, Ekans >= 5", op: "gte", flagVal: "Ekans",
|
||||
compareValue: "5", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=gte, 4 >= Zubat", op: "gte", flagVal: "4",
|
||||
compareValue: "Zubat", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
// Test Op "lte"
|
||||
// TODO: test for non-numeric values.
|
||||
// toNumeric function currently uses os.Exit, which stops tests.
|
||||
// {label: "op=gt, both empty", op: "lte", flagVal: "",
|
||||
// compareValue: "", expectedResultPattern: "'' is lower or equal to ''",
|
||||
// testResult: true},
|
||||
{label: "op=gt, 0 <= 0", op: "lte", flagVal: "0",
|
||||
{label: "op=lte, both empty", op: "lte", flagVal: "",
|
||||
compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=lte, 0 <= 0", op: "lte", flagVal: "0",
|
||||
compareValue: "0", expectedResultPattern: "0 is lower or equal to 0",
|
||||
testResult: true},
|
||||
{label: "op=gt, 4 <= 5", op: "lte", flagVal: "4",
|
||||
{label: "op=lte, 4 <= 5", op: "lte", flagVal: "4",
|
||||
compareValue: "5", expectedResultPattern: "4 is lower or equal to 5",
|
||||
testResult: true},
|
||||
{label: "op=gt, 5 <= 4", op: "lte", flagVal: "5",
|
||||
{label: "op=lte, 5 <= 4", op: "lte", flagVal: "5",
|
||||
compareValue: "4", expectedResultPattern: "5 is lower or equal to 4",
|
||||
testResult: false},
|
||||
{label: "op=gt, 5 <= 5", op: "lte", flagVal: "5",
|
||||
{label: "op=lte, 5 <= 5", op: "lte", flagVal: "5",
|
||||
compareValue: "5", expectedResultPattern: "5 is lower or equal to 5",
|
||||
testResult: true},
|
||||
{label: "op=lte, Venomoth <= 4", op: "lte", flagVal: "Venomoth",
|
||||
compareValue: "4", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
{label: "op=lte, 5 <= Meowth", op: "lte", flagVal: "5",
|
||||
compareValue: "Meowth", expectedResultPattern: "Invalid Number(s) used for comparison",
|
||||
testResult: false},
|
||||
|
||||
// Test Op "has"
|
||||
{label: "op=gt, both empty", op: "has", flagVal: "",
|
||||
{label: "op=has, both empty", op: "has", flagVal: "",
|
||||
compareValue: "", expectedResultPattern: "'' has ''",
|
||||
testResult: true},
|
||||
{label: "op=gt, flagVal=empty", op: "has", flagVal: "",
|
||||
{label: "op=has, flagVal=empty", op: "has", flagVal: "",
|
||||
compareValue: "blah", expectedResultPattern: "'' has 'blah'",
|
||||
testResult: false},
|
||||
{label: "op=gt, compareValue=empty", op: "has", flagVal: "blah",
|
||||
{label: "op=has, compareValue=empty", op: "has", flagVal: "blah",
|
||||
compareValue: "", expectedResultPattern: "'blah' has ''",
|
||||
testResult: true},
|
||||
{label: "op=gt, 'blah' has 'la'", op: "has", flagVal: "blah",
|
||||
{label: "op=has, 'blah' has 'la'", op: "has", flagVal: "blah",
|
||||
compareValue: "la", expectedResultPattern: "'blah' has 'la'",
|
||||
testResult: true},
|
||||
{label: "op=gt, 'blah' has 'LA'", op: "has", flagVal: "blah",
|
||||
{label: "op=has, 'blah' has 'LA'", op: "has", flagVal: "blah",
|
||||
compareValue: "LA", expectedResultPattern: "'blah' has 'LA'",
|
||||
testResult: false},
|
||||
{label: "op=gt, 'blah' has 'lo'", op: "has", flagVal: "blah",
|
||||
{label: "op=has, 'blah' has 'lo'", op: "has", flagVal: "blah",
|
||||
compareValue: "lo", expectedResultPattern: "'blah' has 'lo'",
|
||||
testResult: false},
|
||||
|
||||
// Test Op "nothave"
|
||||
{label: "op=gt, both empty", op: "nothave", flagVal: "",
|
||||
{label: "op=nothave, both empty", op: "nothave", flagVal: "",
|
||||
compareValue: "", expectedResultPattern: " '' not have ''",
|
||||
testResult: false},
|
||||
{label: "op=gt, flagVal=empty", op: "nothave", flagVal: "",
|
||||
{label: "op=nothave, flagVal=empty", op: "nothave", flagVal: "",
|
||||
compareValue: "blah", expectedResultPattern: " '' not have 'blah'",
|
||||
testResult: true},
|
||||
{label: "op=gt, compareValue=empty", op: "nothave", flagVal: "blah",
|
||||
{label: "op=nothave, compareValue=empty", op: "nothave", flagVal: "blah",
|
||||
compareValue: "", expectedResultPattern: " 'blah' not have ''",
|
||||
testResult: false},
|
||||
{label: "op=gt, 'blah' not have 'la'", op: "nothave", flagVal: "blah",
|
||||
{label: "op=nothave, 'blah' not have 'la'", op: "nothave", flagVal: "blah",
|
||||
compareValue: "la", expectedResultPattern: " 'blah' not have 'la'",
|
||||
testResult: false},
|
||||
{label: "op=gt, 'blah' not have 'LA'", op: "nothave", flagVal: "blah",
|
||||
{label: "op=nothave, 'blah' not have 'LA'", op: "nothave", flagVal: "blah",
|
||||
compareValue: "LA", expectedResultPattern: " 'blah' not have 'LA'",
|
||||
testResult: true},
|
||||
{label: "op=gt, 'blah' not have 'lo'", op: "nothave", flagVal: "blah",
|
||||
{label: "op=nothave, 'blah' not have 'lo'", op: "nothave", flagVal: "blah",
|
||||
compareValue: "lo", expectedResultPattern: " 'blah' not have 'lo'",
|
||||
testResult: true},
|
||||
|
||||
// Test Op "regex"
|
||||
{label: "op=gt, both empty", op: "regex", flagVal: "",
|
||||
{label: "op=regex, both empty", op: "regex", flagVal: "",
|
||||
compareValue: "", expectedResultPattern: " '' matched by ''",
|
||||
testResult: true},
|
||||
{label: "op=gt, flagVal=empty", op: "regex", flagVal: "",
|
||||
{label: "op=regex, flagVal=empty", op: "regex", flagVal: "",
|
||||
compareValue: "blah", expectedResultPattern: " '' matched by 'blah'",
|
||||
testResult: false},
|
||||
|
||||
@@ -679,6 +692,12 @@ func TestCompareOp(t *testing.T) {
|
||||
{label: "op=bitmask, 644 AND 211", op: "bitmask", flagVal: "211",
|
||||
compareValue: "644", expectedResultPattern: "bitmask '211' AND '644'",
|
||||
testResult: false},
|
||||
{label: "op=bitmask, Harry AND 211", op: "bitmask", flagVal: "Harry",
|
||||
compareValue: "644", expectedResultPattern: "Not numeric value - flag: Harry",
|
||||
testResult: false},
|
||||
{label: "op=bitmask, 644 AND Potter", op: "bitmask", flagVal: "211",
|
||||
compareValue: "Potter", expectedResultPattern: "Not numeric value - flag: Potter",
|
||||
testResult: false},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
||||
@@ -16,10 +16,13 @@ package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/aquasecurity/kube-bench/check"
|
||||
@@ -63,8 +66,6 @@ func NewRunFilter(opts FilterOpts) (check.Predicate, error) {
|
||||
}
|
||||
|
||||
func runChecks(nodetype check.NodeType, testYamlFile string) {
|
||||
var summary check.Summary
|
||||
|
||||
// Verify config file was loaded into Viper during Cobra sub-command initialization.
|
||||
if configFileError != nil {
|
||||
colorPrint(check.FAIL, fmt.Sprintf("Failed to read config file: %v\n", configFileError))
|
||||
@@ -117,36 +118,8 @@ func runChecks(nodetype check.NodeType, testYamlFile string) {
|
||||
exitWithError(fmt.Errorf("error setting up run filter: %v", err))
|
||||
}
|
||||
|
||||
summary = controls.RunChecks(runner, filter)
|
||||
|
||||
if (summary.Fail > 0 || summary.Warn > 0 || summary.Pass > 0 || summary.Info > 0) && junitFmt {
|
||||
out, err := controls.JUnit()
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("failed to output in JUnit format: %v", err))
|
||||
}
|
||||
|
||||
PrintOutput(string(out), outputFile)
|
||||
// if we successfully ran some tests and it's json format, ignore the warnings
|
||||
} else if (summary.Fail > 0 || summary.Warn > 0 || summary.Pass > 0 || summary.Info > 0) && jsonFmt {
|
||||
out, err := controls.JSON()
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("failed to output in JSON format: %v", err))
|
||||
}
|
||||
|
||||
PrintOutput(string(out), outputFile)
|
||||
} else {
|
||||
// if we want to store in PostgreSQL, convert to JSON and save it
|
||||
if (summary.Fail > 0 || summary.Warn > 0 || summary.Pass > 0 || summary.Info > 0) && pgSQL {
|
||||
out, err := controls.JSON()
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("failed to output in JSON format: %v", err))
|
||||
}
|
||||
|
||||
savePgsql(string(out))
|
||||
} else {
|
||||
prettyPrint(controls, summary)
|
||||
}
|
||||
}
|
||||
controls.RunChecks(runner, filter)
|
||||
controlsCollection = append(controlsCollection, controls)
|
||||
}
|
||||
|
||||
// colorPrint outputs the state in a specific colour, along with a message string
|
||||
@@ -185,7 +158,7 @@ func prettyPrint(r *check.Controls, summary check.Summary) {
|
||||
}
|
||||
if c.State == check.WARN {
|
||||
// Print the error if test failed due to problem with the audit command
|
||||
if c.Reason != "" && c.Type != "manual"{
|
||||
if c.Reason != "" && c.Type != "manual" {
|
||||
fmt.Printf("%s audit test did not run: %s\n", c.ID, c.Reason)
|
||||
} else {
|
||||
fmt.Printf("%s %s\n", c.ID, c.Remediation)
|
||||
@@ -359,6 +332,62 @@ func isThisNodeRunning(nodeType check.NodeType) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func writeOutput(controlsCollection []*check.Controls) {
|
||||
sort.Slice(controlsCollection, func(i, j int) bool {
|
||||
iid, _ := strconv.Atoi(controlsCollection[i].ID)
|
||||
jid, _ := strconv.Atoi(controlsCollection[j].ID)
|
||||
return iid < jid
|
||||
})
|
||||
if junitFmt {
|
||||
writeJunitOutput(controlsCollection)
|
||||
return
|
||||
}
|
||||
if jsonFmt {
|
||||
writeJsonOutput(controlsCollection)
|
||||
return
|
||||
}
|
||||
if pgSQL {
|
||||
writePgsqlOutput(controlsCollection)
|
||||
return
|
||||
}
|
||||
writeStdoutOutput(controlsCollection)
|
||||
}
|
||||
|
||||
func writeJsonOutput(controlsCollection []*check.Controls) {
|
||||
out, err := json.Marshal(controlsCollection)
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("failed to output in JSON format: %v", err))
|
||||
}
|
||||
PrintOutput(string(out), outputFile)
|
||||
}
|
||||
|
||||
func writeJunitOutput(controlsCollection []*check.Controls) {
|
||||
for _, controls := range controlsCollection {
|
||||
out, err := controls.JUnit()
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("failed to output in JUnit format: %v", err))
|
||||
}
|
||||
PrintOutput(string(out), outputFile)
|
||||
}
|
||||
}
|
||||
|
||||
func writePgsqlOutput(controlsCollection []*check.Controls) {
|
||||
for _, controls := range controlsCollection {
|
||||
out, err := controls.JSON()
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("failed to output in Postgresql format: %v", err))
|
||||
}
|
||||
savePgsql(string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func writeStdoutOutput(controlsCollection []*check.Controls) {
|
||||
for _, controls := range controlsCollection {
|
||||
summary := controls.Summary
|
||||
prettyPrint(controls, summary)
|
||||
}
|
||||
}
|
||||
|
||||
func printRawOutput(output string) {
|
||||
for _, row := range strings.Split(output, "\n") {
|
||||
fmt.Println(fmt.Sprintf("\t %s", row))
|
||||
|
||||
@@ -15,12 +15,15 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aquasecurity/kube-bench/check"
|
||||
"github.com/spf13/viper"
|
||||
@@ -475,6 +478,51 @@ func TestIsEtcd(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteResultToJsonFile(t *testing.T) {
|
||||
defer func() {
|
||||
controlsCollection = []*check.Controls{}
|
||||
jsonFmt = false
|
||||
outputFile = ""
|
||||
}()
|
||||
var err error
|
||||
jsonFmt = true
|
||||
outputFile = path.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().UnixNano()))
|
||||
|
||||
controlsCollection, err = parseControlsJsonFile("./testdata/controlsCollection.json")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
writeOutput(controlsCollection)
|
||||
|
||||
var expect []*check.Controls
|
||||
var result []*check.Controls
|
||||
result, err = parseControlsJsonFile(outputFile)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
expect, err = parseControlsJsonFile("./testdata/result.json")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, expect, result)
|
||||
}
|
||||
|
||||
func parseControlsJsonFile(filepath string) ([]*check.Controls, error) {
|
||||
var result []*check.Controls
|
||||
|
||||
d, err := ioutil.ReadFile(filepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(d, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func loadConfigForTest() (*viper.Viper, error) {
|
||||
viperWithData := viper.New()
|
||||
viperWithData.SetConfigFile(filepath.Join("..", cfgDir, "config.yaml"))
|
||||
|
||||
@@ -27,6 +27,7 @@ var masterCmd = &cobra.Command{
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
filename := loadConfig(check.MASTER)
|
||||
runChecks(check.MASTER, filename)
|
||||
writeOutput(controlsCollection)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ var nodeCmd = &cobra.Command{
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
filename := loadConfig(check.NODE)
|
||||
runChecks(check.NODE, filename)
|
||||
writeOutput(controlsCollection)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ var (
|
||||
includeTestOutput bool
|
||||
outputFile string
|
||||
configFileError error
|
||||
controlsCollection []*check.Controls
|
||||
)
|
||||
|
||||
// RootCmd represents the base command when called without any subcommands
|
||||
@@ -104,6 +105,7 @@ var RootCmd = &cobra.Command{
|
||||
runChecks(check.MANAGEDSERVICES, loadConfig(check.MANAGEDSERVICES))
|
||||
}
|
||||
|
||||
writeOutput(controlsCollection)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ func run(targets []string, benchmarkVersion string) (err error) {
|
||||
runChecks(testType, yamlFile)
|
||||
}
|
||||
|
||||
writeOutput(controlsCollection)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
114
cmd/testdata/controlsCollection.json
vendored
Normal file
114
cmd/testdata/controlsCollection.json
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
[
|
||||
{
|
||||
"id": "2",
|
||||
"version": "1.15",
|
||||
"text": "Etcd Node Configuration",
|
||||
"node_type": "etcd",
|
||||
"tests": [
|
||||
{
|
||||
"section": "2",
|
||||
"pass": 7,
|
||||
"fail": 0,
|
||||
"warn": 0,
|
||||
"info": 0,
|
||||
"desc": "Etcd Node Configuration Files",
|
||||
"results": [
|
||||
{
|
||||
"test_number": "2.1",
|
||||
"test_desc": "Ensure that the --cert-file and --key-file arguments are set as appropriate (Scored)",
|
||||
"audit": "/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep",
|
||||
"AuditConfig": "",
|
||||
"type": "",
|
||||
"remediation": "Follow the etcd service documentation and configure TLS encryption.\nThen, edit the etcd pod specification file /etc/kubernetes/manifests/etcd.yaml\non the master node and set the below parameters.\n--cert-file=</path/to/ca-file>\n--key-file=</path/to/key-file>\n",
|
||||
"test_info": [
|
||||
"Follow the etcd service documentation and configure TLS encryption.\nThen, edit the etcd pod specification file /etc/kubernetes/manifests/etcd.yaml\non the master node and set the below parameters.\n--cert-file=</path/to/ca-file>\n--key-file=</path/to/key-file>\n"
|
||||
],
|
||||
"status": "PASS",
|
||||
"actual_value": "root 3277 3218 3 Apr19 ? 03:57:52 etcd --advertise-client-urls=https://192.168.64.4:2379 --cert-file=/var/lib/minikube/certs/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/minikube/etcd --initial-advertise-peer-urls=https://192.168.64.4:2380 --initial-cluster=minikube=https://192.168.64.4:2380 --key-file=/var/lib/minikube/certs/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.64.4:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.64.4:2380 --name=minikube --peer-cert-file=/var/lib/minikube/certs/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/var/lib/minikube/certs/etcd/peer.key --peer-trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt --snapshot-count=10000 --trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt\nroot 4624 4605 8 Apr21 ? 04:55:10 kube-apiserver --advertise-address=192.168.64.4 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/var/lib/minikube/certs/ca.crt --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodSecurityPolicy --enable-bootstrap-token-auth=true --etcd-cafile=/var/lib/minikube/certs/etcd/ca.crt --etcd-certfile=/var/lib/minikube/certs/apiserver-etcd-client.crt --etcd-keyfile=/var/lib/minikube/certs/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/var/lib/minikube/certs/apiserver-kubelet-client.crt --kubelet-client-key=/var/lib/minikube/certs/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/var/lib/minikube/certs/front-proxy-client.crt --proxy-client-key-file=/var/lib/minikube/certs/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=8443 --service-account-key-file=/var/lib/minikube/certs/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/var/lib/minikube/certs/apiserver.crt --tls-private-key-file=/var/lib/minikube/certs/apiserver.key\n",
|
||||
"scored": true,
|
||||
"expected_result": "'--cert-file' is present AND '--key-file' is present"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total_pass": 7,
|
||||
"total_fail": 0,
|
||||
"total_warn": 0,
|
||||
"total_info": 0
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"version": "1.5",
|
||||
"text": "Control Plane Configuration",
|
||||
"node_type": "controlplane",
|
||||
"tests": [
|
||||
{
|
||||
"section": "3.1",
|
||||
"pass": 0,
|
||||
"fail": 0,
|
||||
"warn": 1,
|
||||
"info": 0,
|
||||
"desc": "Authentication and Authorization",
|
||||
"results": [
|
||||
{
|
||||
"test_number": "3.1.1",
|
||||
"test_desc": "Client certificate authentication should not be used for users (Not Scored)",
|
||||
"audit": "",
|
||||
"AuditConfig": "",
|
||||
"type": "manual",
|
||||
"remediation": "Alternative mechanisms provided by Kubernetes such as the use of OIDC should be\nimplemented in place of client certificates.\n",
|
||||
"test_info": [
|
||||
"Alternative mechanisms provided by Kubernetes such as the use of OIDC should be\nimplemented in place of client certificates.\n"
|
||||
],
|
||||
"status": "WARN",
|
||||
"actual_value": "",
|
||||
"scored": false,
|
||||
"expected_result": "",
|
||||
"reason": "Test marked as a manual test"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total_pass": 0,
|
||||
"total_fail": 0,
|
||||
"total_warn": 3,
|
||||
"total_info": 0
|
||||
},
|
||||
{
|
||||
"id": "1",
|
||||
"version": "1.5",
|
||||
"text": "Master Node Security Configuration",
|
||||
"node_type": "master",
|
||||
"tests": [
|
||||
{
|
||||
"section": "1.1",
|
||||
"pass": 15,
|
||||
"fail": 1,
|
||||
"warn": 5,
|
||||
"info": 0,
|
||||
"desc": "Master Node Configuration Files",
|
||||
"results": [
|
||||
{
|
||||
"test_number": "1.1.1",
|
||||
"test_desc": "Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Scored)",
|
||||
"audit": "/bin/sh -c 'if test -e /etc/kubernetes/manifests/kube-apiserver.yaml; then stat -c permissions=%a /etc/kubernetes/manifests/kube-apiserver.yaml; fi'",
|
||||
"AuditConfig": "",
|
||||
"type": "",
|
||||
"remediation": "Run the below command (based on the file location on your system) on the\nmaster node.\nFor example, chmod 644 /etc/kubernetes/manifests/kube-apiserver.yaml\n",
|
||||
"test_info": [
|
||||
"Run the below command (based on the file location on your system) on the\nmaster node.\nFor example, chmod 644 /etc/kubernetes/manifests/kube-apiserver.yaml\n"
|
||||
],
|
||||
"status": "PASS",
|
||||
"actual_value": "permissions=600\n",
|
||||
"scored": true,
|
||||
"expected_result": "bitmask '600' AND '644'"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total_pass": 42,
|
||||
"total_fail": 12,
|
||||
"total_warn": 11,
|
||||
"total_info": 0
|
||||
}
|
||||
]
|
||||
114
cmd/testdata/result.json
vendored
Normal file
114
cmd/testdata/result.json
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"version": "1.5",
|
||||
"text": "Master Node Security Configuration",
|
||||
"node_type": "master",
|
||||
"tests": [
|
||||
{
|
||||
"section": "1.1",
|
||||
"pass": 15,
|
||||
"fail": 1,
|
||||
"warn": 5,
|
||||
"info": 0,
|
||||
"desc": "Master Node Configuration Files",
|
||||
"results": [
|
||||
{
|
||||
"test_number": "1.1.1",
|
||||
"test_desc": "Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Scored)",
|
||||
"audit": "/bin/sh -c 'if test -e /etc/kubernetes/manifests/kube-apiserver.yaml; then stat -c permissions=%a /etc/kubernetes/manifests/kube-apiserver.yaml; fi'",
|
||||
"AuditConfig": "",
|
||||
"type": "",
|
||||
"remediation": "Run the below command (based on the file location on your system) on the\nmaster node.\nFor example, chmod 644 /etc/kubernetes/manifests/kube-apiserver.yaml\n",
|
||||
"test_info": [
|
||||
"Run the below command (based on the file location on your system) on the\nmaster node.\nFor example, chmod 644 /etc/kubernetes/manifests/kube-apiserver.yaml\n"
|
||||
],
|
||||
"status": "PASS",
|
||||
"actual_value": "permissions=600\n",
|
||||
"scored": true,
|
||||
"expected_result": "bitmask '600' AND '644'"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total_pass": 42,
|
||||
"total_fail": 12,
|
||||
"total_warn": 11,
|
||||
"total_info": 0
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"version": "1.15",
|
||||
"text": "Etcd Node Configuration",
|
||||
"node_type": "etcd",
|
||||
"tests": [
|
||||
{
|
||||
"section": "2",
|
||||
"pass": 7,
|
||||
"fail": 0,
|
||||
"warn": 0,
|
||||
"info": 0,
|
||||
"desc": "Etcd Node Configuration Files",
|
||||
"results": [
|
||||
{
|
||||
"test_number": "2.1",
|
||||
"test_desc": "Ensure that the --cert-file and --key-file arguments are set as appropriate (Scored)",
|
||||
"audit": "/bin/ps -ef | /bin/grep etcd | /bin/grep -v grep",
|
||||
"AuditConfig": "",
|
||||
"type": "",
|
||||
"remediation": "Follow the etcd service documentation and configure TLS encryption.\nThen, edit the etcd pod specification file /etc/kubernetes/manifests/etcd.yaml\non the master node and set the below parameters.\n--cert-file=</path/to/ca-file>\n--key-file=</path/to/key-file>\n",
|
||||
"test_info": [
|
||||
"Follow the etcd service documentation and configure TLS encryption.\nThen, edit the etcd pod specification file /etc/kubernetes/manifests/etcd.yaml\non the master node and set the below parameters.\n--cert-file=</path/to/ca-file>\n--key-file=</path/to/key-file>\n"
|
||||
],
|
||||
"status": "PASS",
|
||||
"actual_value": "root 3277 3218 3 Apr19 ? 03:57:52 etcd --advertise-client-urls=https://192.168.64.4:2379 --cert-file=/var/lib/minikube/certs/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/minikube/etcd --initial-advertise-peer-urls=https://192.168.64.4:2380 --initial-cluster=minikube=https://192.168.64.4:2380 --key-file=/var/lib/minikube/certs/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.64.4:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.64.4:2380 --name=minikube --peer-cert-file=/var/lib/minikube/certs/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/var/lib/minikube/certs/etcd/peer.key --peer-trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt --snapshot-count=10000 --trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt\nroot 4624 4605 8 Apr21 ? 04:55:10 kube-apiserver --advertise-address=192.168.64.4 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/var/lib/minikube/certs/ca.crt --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodSecurityPolicy --enable-bootstrap-token-auth=true --etcd-cafile=/var/lib/minikube/certs/etcd/ca.crt --etcd-certfile=/var/lib/minikube/certs/apiserver-etcd-client.crt --etcd-keyfile=/var/lib/minikube/certs/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/var/lib/minikube/certs/apiserver-kubelet-client.crt --kubelet-client-key=/var/lib/minikube/certs/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/var/lib/minikube/certs/front-proxy-client.crt --proxy-client-key-file=/var/lib/minikube/certs/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=8443 --service-account-key-file=/var/lib/minikube/certs/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/var/lib/minikube/certs/apiserver.crt --tls-private-key-file=/var/lib/minikube/certs/apiserver.key\n",
|
||||
"scored": true,
|
||||
"expected_result": "'--cert-file' is present AND '--key-file' is present"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total_pass": 7,
|
||||
"total_fail": 0,
|
||||
"total_warn": 0,
|
||||
"total_info": 0
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"version": "1.5",
|
||||
"text": "Control Plane Configuration",
|
||||
"node_type": "controlplane",
|
||||
"tests": [
|
||||
{
|
||||
"section": "3.1",
|
||||
"pass": 0,
|
||||
"fail": 0,
|
||||
"warn": 1,
|
||||
"info": 0,
|
||||
"desc": "Authentication and Authorization",
|
||||
"results": [
|
||||
{
|
||||
"test_number": "3.1.1",
|
||||
"test_desc": "Client certificate authentication should not be used for users (Not Scored)",
|
||||
"audit": "",
|
||||
"AuditConfig": "",
|
||||
"type": "manual",
|
||||
"remediation": "Alternative mechanisms provided by Kubernetes such as the use of OIDC should be\nimplemented in place of client certificates.\n",
|
||||
"test_info": [
|
||||
"Alternative mechanisms provided by Kubernetes such as the use of OIDC should be\nimplemented in place of client certificates.\n"
|
||||
],
|
||||
"status": "WARN",
|
||||
"actual_value": "",
|
||||
"scored": false,
|
||||
"expected_result": "",
|
||||
"reason": "Test marked as a manual test"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total_pass": 0,
|
||||
"total_fail": 0,
|
||||
"total_warn": 3,
|
||||
"total_info": 0
|
||||
}
|
||||
]
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
var kubebenchImg = flag.String("kubebenchImg", "aquasec/kube-bench:latest", "kube-bench image used as part of this test")
|
||||
var timeout = flag.Duration("timeout", 10*time.Minute, "Test Timeout")
|
||||
|
||||
func TestRunWithKind(t *testing.T) {
|
||||
func testCheckCISWithKind(t *testing.T, testdataDir string) {
|
||||
flag.Parse()
|
||||
fmt.Printf("kube-bench Container Image: %s\n", *kubebenchImg)
|
||||
|
||||
@@ -29,20 +29,20 @@ func TestRunWithKind(t *testing.T) {
|
||||
{
|
||||
TestName: "kube-bench",
|
||||
KubebenchYAML: "../job.yaml",
|
||||
ExpectedFile: "./testdata/job.data",
|
||||
ExpectedFile: fmt.Sprintf("./testdata/%s/job.data", testdataDir),
|
||||
},
|
||||
{
|
||||
TestName: "kube-bench-node",
|
||||
KubebenchYAML: "../job-node.yaml",
|
||||
ExpectedFile: "./testdata/job-node.data",
|
||||
ExpectedFile: fmt.Sprintf("./testdata/%s/job-node.data", testdataDir),
|
||||
},
|
||||
{
|
||||
TestName: "kube-bench-master",
|
||||
KubebenchYAML: "../job-master.yaml",
|
||||
ExpectedFile: "./testdata/job-master.data",
|
||||
ExpectedFile: fmt.Sprintf("./testdata/%s/job-master.data", testdataDir),
|
||||
},
|
||||
}
|
||||
ctx, err := setupCluster("kube-bench", "./testdata/add-tls-kind-k8s114.yaml", *timeout)
|
||||
ctx, err := setupCluster("kube-bench", fmt.Sprintf("./testdata/%s/add-tls-kind.yaml", testdataDir), *timeout)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to setup KIND cluster error: %v", err)
|
||||
}
|
||||
@@ -80,6 +80,18 @@ func TestRunWithKind(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckCIS13WithKind(t *testing.T) {
|
||||
testCheckCISWithKind(t, "cis-1.3")
|
||||
}
|
||||
|
||||
func TestCheckCIS14WithKind(t *testing.T) {
|
||||
testCheckCISWithKind(t, "cis-1.4")
|
||||
}
|
||||
|
||||
func TestCheckCIS15WithKind(t *testing.T) {
|
||||
testCheckCISWithKind(t, "cis-1.5")
|
||||
}
|
||||
|
||||
// This is simple "diff" between 2 strings containing multiple lines.
|
||||
// It's not a comprehensive diff between the 2 strings.
|
||||
// It does not inditcate when lines are deleted.
|
||||
|
||||
19
integration/testdata/cis-1.3/add-tls-kind.yaml
vendored
Normal file
19
integration/testdata/cis-1.3/add-tls-kind.yaml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
apiVersion: kind.sigs.k8s.io/v1alpha3
|
||||
kind: Cluster
|
||||
networking:
|
||||
apiServerAddress: "0.0.0.0"
|
||||
|
||||
kubeadmConfigPatchesJson6902:
|
||||
- group: kubelet.config.k8s.io
|
||||
version: v1beta1
|
||||
kind: KubeletConfiguration
|
||||
patch: |
|
||||
- op: add
|
||||
path: /tlsCipherSuites
|
||||
value: ["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"]
|
||||
|
||||
nodes:
|
||||
# the control plane node config
|
||||
- role: control-plane
|
||||
image: "kindest/node:v1.12.10"
|
||||
336
integration/testdata/cis-1.3/job-master.data
vendored
Normal file
336
integration/testdata/cis-1.3/job-master.data
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
[INFO] 1 Master Node Security Configuration
|
||||
[INFO] 1.1 API Server
|
||||
[FAIL] 1.1.1 Ensure that the --anonymous-auth argument is set to false (Scored)
|
||||
[PASS] 1.1.2 Ensure that the --basic-auth-file argument is not set (Scored)
|
||||
[PASS] 1.1.3 Ensure that the --insecure-allow-any-token argument is not set (Scored)
|
||||
[PASS] 1.1.4 Ensure that the --kubelet-https argument is set to true (Scored)
|
||||
[PASS] 1.1.5 Ensure that the --insecure-bind-address argument is not set (Scored)
|
||||
[PASS] 1.1.6 Ensure that the --insecure-port argument is set to 0 (Scored)
|
||||
[PASS] 1.1.7 Ensure that the --secure-port argument is not set to 0 (Scored)
|
||||
[FAIL] 1.1.8 Ensure that the --profiling argument is set to false (Scored)
|
||||
[FAIL] 1.1.9 Ensure that the --repair-malformed-updates argument is set to false (Scored)
|
||||
[PASS] 1.1.10 Ensure that the admission control plugin AlwaysAdmit is not set (Scored)
|
||||
[FAIL] 1.1.11 Ensure that the admission control plugin AlwaysPullImages is set (Scored)
|
||||
[FAIL] 1.1.12 Ensure that the admission control plugin DenyEscalatingExec is set (Scored)
|
||||
[FAIL] 1.1.13 Ensure that the admission control plugin SecurityContextDeny is set (Scored)
|
||||
[PASS] 1.1.14 Ensure that the admission control plugin NamespaceLifecycle is set (Scored)
|
||||
[FAIL] 1.1.15 Ensure that the --audit-log-path argument is set as appropriate (Scored)
|
||||
[FAIL] 1.1.16 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Scored)
|
||||
[FAIL] 1.1.17 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Scored)
|
||||
[FAIL] 1.1.18 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Scored)
|
||||
[PASS] 1.1.19 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 1.1.20 Ensure that the --token-auth-file parameter is not set (Scored)
|
||||
[FAIL] 1.1.21 Ensure that the --kubelet-certificate-authority argument is set as appropriate (Scored)
|
||||
[PASS] 1.1.22 Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Scored)
|
||||
[FAIL] 1.1.23 Ensure that the --service-account-lookup argument is set to true (Scored)
|
||||
[FAIL] 1.1.24 Ensure that the admission control plugin PodSecurityPolicy is set (Scored)
|
||||
[PASS] 1.1.25 Ensure that the --service-account-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.1.26 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored)
|
||||
[FAIL] 1.1.27 Ensure that the admission control plugin ServiceAccount is set(Scored)
|
||||
[PASS] 1.1.28 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.1.29 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[WARN] 1.1.30 Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
[PASS] 1.1.31 Ensure that the --etcd-cafile argument is set as appropriate (Scored)
|
||||
[PASS] 1.1.32 Ensure that the --authorization-mode argument is set to Node (Scored)
|
||||
[PASS] 1.1.33 Ensure that the admission control plugin NodeRestriction is set (Scored)
|
||||
[FAIL] 1.1.34 Ensure that the --experimental-encryption-provider-config argument is set as appropriate (Scored)
|
||||
[WARN] 1.1.35 Ensure that the encryption provider is set to aescbc (Scored)
|
||||
[FAIL] 1.1.36 Ensure that the admission control plugin EventRateLimit is set (Scored)
|
||||
[PASS] 1.1.37a Ensure that the AdvancedAuditing argument is not set to false (Scored)
|
||||
[FAIL] 1.1.37b Ensure that the AdvancedAuditing argument is not set to false (Scored)
|
||||
[PASS] 1.1.38 Ensure that the --request-timeout argument is set as appropriate (Scored)
|
||||
[WARN] 1.1.39 Ensure that the API Server only makes use of Strong Cryptographic Ciphers ( Not Scored)
|
||||
[INFO] 1.2 Scheduler
|
||||
[FAIL] 1.2.1 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.2.2 Ensure that the --address argument is set to 127.0.0.1 (Scored)
|
||||
[INFO] 1.3 Controller Manager
|
||||
[FAIL] 1.3.1 Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.2 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.3.3 Ensure that the --use-service-account-credentials argument is set to true (Scored)
|
||||
[PASS] 1.3.4 Ensure that the --service-account-private-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.3.5 Ensure that the --root-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.6 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[PASS] 1.3.7 Ensure that the --address argument is set to 127.0.0.1 (Scored)
|
||||
[INFO] 1.4 Configuration Files
|
||||
[PASS] 1.4.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.2 Ensure that the API server pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.3 Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.4 Ensure that the controller manager pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.5 Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.6 Ensure that the scheduler pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.7 Ensure that the etcd pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.8 Ensure that the etcd pod specification file ownership is set to root:root (Scored)
|
||||
[WARN] 1.4.9 Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Not Scored)
|
||||
[WARN] 1.4.10 Ensure that the Container Network Interface file ownership is set to root:root (Not Scored)
|
||||
[FAIL] 1.4.11 Ensure that the etcd data directory permissions are set to 700 or more restrictive (Scored)
|
||||
[FAIL] 1.4.12 Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)
|
||||
[PASS] 1.4.13 Ensure that the admin.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.14 Ensure that the admin.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.15 Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.16 Ensure that the scheduler.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.17 Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.18 Ensure that the controller-manager.conf file ownership is set to root:root (Scored)
|
||||
[INFO] 1.5 etcd
|
||||
[PASS] 1.5.1 Ensure that the --cert-file and --key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.5.2 Ensure that the --client-cert-auth argument is set to true (Scored)
|
||||
[PASS] 1.5.3 Ensure that the --auto-tls argument is not set to true (Scored)
|
||||
[PASS] 1.5.4 Ensure that the --peer-cert-file and --peer-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.5.5 Ensure that the --peer-client-cert-auth argument is set to true (Scored)
|
||||
[PASS] 1.5.6 Ensure that the --peer-auto-tls argument is not set to true (Scored)
|
||||
[WARN] 1.5.7 Ensure that a unique Certificate Authority is used for etcd (Not Scored)
|
||||
[INFO] 1.6 General Security Primitives
|
||||
[WARN] 1.6.1 Ensure that the cluster-admin role is only used where required (Not Scored)
|
||||
[WARN] 1.6.2 Create administrative boundaries between resources using namespaces (Not Scored)
|
||||
[WARN] 1.6.3 Create network segmentation using Network Policies (Not Scored)
|
||||
[WARN] 1.6.4 Ensure that the seccomp profile is set to docker/default in your pod definitions (Not Scored)
|
||||
[WARN] 1.6.5 Apply Security Context to Your Pods and Containers (Not Scored)
|
||||
[WARN] 1.6.6 Configure Image Provenance using ImagePolicyWebhook admission controller (Not Scored)
|
||||
[WARN] 1.6.7 Configure Network policies as appropriate (Not Scored)
|
||||
[WARN] 1.6.8 Place compensating controls in the form of PSP and RBAC for privileged containers usage (Not Scored)
|
||||
[INFO] 1.7 PodSecurityPolicies
|
||||
[WARN] 1.7.1 Do not admit privileged containers (Not Scored)
|
||||
[WARN] 1.7.2 Do not admit containers wishing to share the host process ID namespace (Scored)
|
||||
[WARN] 1.7.3 Do not admit containers wishing to share the host IPC namespace (Scored)
|
||||
[WARN] 1.7.4 Do not admit containers wishing to share the host network namespace (Scored)
|
||||
[WARN] 1.7.5 Do not admit containers with allowPrivilegeEscalation (Scored)
|
||||
[WARN] 1.7.6 Do not admit root containers (Not Scored)
|
||||
[WARN] 1.7.7 Do not admit containers with dangerous capabilities (Not Scored)
|
||||
|
||||
== Remediations ==
|
||||
1.1.1 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
|
||||
1.1.8 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.1.9 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--repair-malformed-updates=false
|
||||
|
||||
1.1.11 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins to
|
||||
include AlwaysPullImages.
|
||||
--enable-admission-plugins=...,AlwaysPullImages,...
|
||||
|
||||
1.1.12 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes DenyEscalatingExec.
|
||||
--enable-admission-plugins=...,DenyEscalatingExec,...
|
||||
|
||||
1.1.13 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to
|
||||
include SecurityContextDeny.
|
||||
--enable-admission-plugins=...,SecurityContextDeny,...
|
||||
|
||||
1.1.15 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-path parameter to a suitable
|
||||
path and file where you would like audit logs to be written, for example:
|
||||
--audit-log-path=/var/log/apiserver/audit.log
|
||||
|
||||
1.1.16 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxage parameter to 30 or
|
||||
as an appropriate number of days: --audit-log-maxage=30
|
||||
|
||||
1.1.17 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxbackup parameter to 10
|
||||
or to an appropriate value.
|
||||
--audit-log-maxbackup=10
|
||||
|
||||
1.1.18 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxsize parameter to an
|
||||
appropriate size in MB. For example, to set it as 100 MB:
|
||||
--audit-log-maxsize=100
|
||||
|
||||
1.1.21 Follow the Kubernetes documentation and setup the TLS connection between the
|
||||
apiserver and kubelets. Then, edit the API server pod specification file
|
||||
/etc/kubernetes/manifests/kube-apiserver.yaml on the master node and set the --kubelet-certificate-authority
|
||||
parameter to the path to the cert file for the certificate authority.
|
||||
--kubelet-certificate-authority=<ca-string>
|
||||
|
||||
1.1.23 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--service-account-lookup=true
|
||||
|
||||
1.1.24 Follow the documentation and create Pod Security Policy objects as per your environment.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes PodSecurityPolicy :
|
||||
--enable-admission-plugins=...,PodSecurityPolicy,...
|
||||
Then restart the API Server.
|
||||
|
||||
1.1.27 Follow the documentation and create ServiceAccount objects as per your environment.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes ServiceAccount.
|
||||
--enable-admission-plugins=...,ServiceAccount,...
|
||||
|
||||
1.1.30 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
1.1.34 Follow the Kubernetes documentation and configure a EncryptionConfig file.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml on the
|
||||
master node and set the --experimental-encryption-provider-config parameter
|
||||
to the path of that file:
|
||||
--experimental-encryption-provider-config=</path/to/EncryptionConfig/File>
|
||||
|
||||
1.1.35 [Manual test]
|
||||
Follow the Kubernetes documentation and configure a EncryptionConfig file. In this file,
|
||||
choose aescbc as the encryption provider.
|
||||
For example,
|
||||
kind: EncryptionConfig
|
||||
apiVersion: v1
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: <32-byte base64-encoded secret>
|
||||
|
||||
1.1.36 Follow the Kubernetes documentation and set the desired limits in a
|
||||
configuration file. Then, edit the API server pod specification file
|
||||
/etc/kubernetes/manifests/kube-apiserver.yaml and set the below parameters.
|
||||
--enable-admission-plugins=...,EventRateLimit,...
|
||||
--admission-control-config-file=<path/to/configuration/file>
|
||||
|
||||
1.1.37b Follow the Kubernetes documentation and set the desired audit policy in the
|
||||
/etc/kubernetes/audit-policy.yaml file. Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
and set the below parameters.
|
||||
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
|
||||
|
||||
1.1.39 Edit the API server pod specification file /etc/kubernetes/manifests
|
||||
kube-apiserver.yaml on the master node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
1.2.1 Edit the Scheduler pod specification file /etc/kubernetes/manifests/kube-scheduler.yaml
|
||||
file on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.3.1 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the --terminated-pod-gc-threshold to an appropriate threshold, for example:
|
||||
--terminated-pod-gc-threshold=10
|
||||
|
||||
1.3.2 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.3.6 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
controller-manager.yaml on the master node and set the --feature-gates parameter to
|
||||
include RotateKubeletServerCertificate=true.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
|
||||
1.4.9 [Manual test]
|
||||
Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod 644 <path/to/cni/files>
|
||||
|
||||
1.4.10 [Manual test]
|
||||
Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chown root:root <path/to/cni/files>
|
||||
|
||||
1.4.11 On the etcd server node, get the etcd data directory, passed as an argument --data-dir ,
|
||||
from the below command:
|
||||
ps -ef | grep etcd
|
||||
Run the below command (based on the etcd data directory found above). For example,
|
||||
chmod 700 /var/lib/etcd
|
||||
|
||||
1.4.12 On the etcd server node, get the etcd data directory, passed as an argument --data-dir ,
|
||||
from the below command:
|
||||
ps -ef | grep etcd
|
||||
Run the below command (based on the etcd data directory found above). For example,
|
||||
chown etcd:etcd /var/lib/etcd
|
||||
|
||||
1.5.7 [Manual test]
|
||||
Follow the etcd documentation and create a dedicated certificate authority setup for the
|
||||
etcd service.
|
||||
Then, edit the etcd pod specification file /etc/kubernetes/manifests/etcd.yaml on the
|
||||
master node and set the below parameter.
|
||||
--trusted-ca-file=</path/to/ca-file>
|
||||
|
||||
1.6.1 [Manual test]
|
||||
Remove any unneeded clusterrolebindings :
|
||||
kubectl delete clusterrolebinding [name]
|
||||
|
||||
1.6.2 [Manual test]
|
||||
Follow the documentation and create namespaces for objects in your deployment as you
|
||||
need them.
|
||||
|
||||
1.6.3 [Manual test]
|
||||
Follow the documentation and create NetworkPolicy objects as you need them.
|
||||
|
||||
1.6.4 [Manual test]
|
||||
Seccomp is an alpha feature currently. By default, all alpha features are disabled. So, you
|
||||
would need to enable alpha features in the apiserver by passing "--feature-
|
||||
gates=AllAlpha=true" argument.
|
||||
Edit the /etc/kubernetes/manifests/kube-apiserver.yaml file on the master node and set the KUBE_API_ARGS
|
||||
parameter to "--feature-gates=AllAlpha=true"
|
||||
KUBE_API_ARGS="--feature-gates=AllAlpha=true"
|
||||
Based on your system, restart the kube-apiserver service. For example:
|
||||
systemctl restart kube-apiserver.service
|
||||
Use annotations to enable the docker/default seccomp profile in your pod definitions. An
|
||||
example is as below:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: trustworthy-pod
|
||||
annotations:
|
||||
seccomp.security.alpha.kubernetes.io/pod: docker/default
|
||||
spec:
|
||||
containers:
|
||||
- name: trustworthy-container
|
||||
image: sotrustworthy:latest
|
||||
|
||||
1.6.5 [Manual test]
|
||||
Follow the Kubernetes documentation and apply security contexts to your pods. For a
|
||||
suggested list of security contexts, you may refer to the CIS Security Benchmark for Docker
|
||||
Containers.
|
||||
|
||||
1.6.6 [Manual test]
|
||||
Follow the Kubernetes documentation and setup image provenance.
|
||||
|
||||
1.6.7 [Manual test]
|
||||
Follow the Kubernetes documentation and setup network policies as appropriate.
|
||||
For example, you could create a "default" isolation policy for a Namespace by creating a
|
||||
NetworkPolicy that selects all pods but does not allow any traffic:
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: default-deny
|
||||
spec:
|
||||
podSelector:
|
||||
|
||||
1.6.8 [Manual test]
|
||||
Follow Kubernetes documentation and setup PSP and RBAC authorization for your cluster.
|
||||
|
||||
1.7.1 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.privileged field is omitted or set to false.
|
||||
|
||||
1.7.2 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.hostPID field is omitted or set to false.
|
||||
|
||||
1.7.3 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.hostIPC field is omitted or set to false.
|
||||
|
||||
1.7.4 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.hostNetwork field is omitted or set to false.
|
||||
|
||||
1.7.5 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.allowPrivilegeEscalation field is omitted or set to false.
|
||||
|
||||
1.7.6 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.runAsUser.rule is set to either MustRunAsNonRoot or MustRunAs with the range of UIDs not including 0.
|
||||
|
||||
1.7.7 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.requiredDropCapabilities is set to include either NET_RAW or ALL.
|
||||
|
||||
|
||||
== Summary ==
|
||||
45 checks PASS
|
||||
23 checks FAIL
|
||||
21 checks WARN
|
||||
0 checks INFO
|
||||
104
integration/testdata/cis-1.3/job-node.data
vendored
Normal file
104
integration/testdata/cis-1.3/job-node.data
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
[INFO] 2 Worker Node Security Configuration
|
||||
[INFO] 2.1 Kubelet
|
||||
[FAIL] 2.1.1 Ensure that the --allow-privileged argument is set to false (Scored)
|
||||
[PASS] 2.1.2 Ensure that the --anonymous-auth argument is set to false (Scored)
|
||||
[PASS] 2.1.3 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 2.1.4 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 2.1.5 Ensure that the --read-only-port argument is set to 0 (Scored)
|
||||
[PASS] 2.1.6 Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)
|
||||
[FAIL] 2.1.7 Ensure that the --protect-kernel-defaults argument is set to true (Scored)
|
||||
[PASS] 2.1.8 Ensure that the --make-iptables-util-chains argument is set to true (Scored)
|
||||
[PASS] 2.1.9 Ensure that the --hostname-override argument is not set (Scored)
|
||||
[FAIL] 2.1.10 Ensure that the --event-qps argument is set to 0 (Scored)
|
||||
[FAIL] 2.1.11 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 2.1.12 Ensure that the --cadvisor-port argument is set to 0 (Scored)
|
||||
[PASS] 2.1.13 Ensure that the --rotate-certificates argument is not set to false (Scored)
|
||||
[FAIL] 2.1.14 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[WARN] 2.1.15 Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
[INFO] 2.2 Configuration Files
|
||||
[PASS] 2.2.1 Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 2.2.2 Ensure that the kubelet.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 2.2.3 Ensure that the kubelet service file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 2.2.4 Ensure that the kubelet service file ownership is set to root:root (Scored)
|
||||
[FAIL] 2.2.5 Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)
|
||||
[FAIL] 2.2.6 Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)
|
||||
[WARN] 2.2.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 2.2.8 Ensure that the client certificate authorities file ownership is set to root:root (Scored)
|
||||
[PASS] 2.2.9 Ensure that the kubelet configuration file ownership is set to root:root (Scored)
|
||||
[PASS] 2.2.10 Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)
|
||||
|
||||
== Remediations ==
|
||||
2.1.1 Edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
on each worker node and set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--allow-privileged=false
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.5 If using a Kubelet config file, edit the file to set readOnlyPort to 0 .
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--read-only-port=0
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.7 If using a Kubelet config file, edit the file to set protectKernelDefaults: true .
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--protect-kernel-defaults=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.10 If using a Kubelet config file, edit the file to set eventRecordQPS: 0 .
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--event-qps=0
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.11 If using a Kubelet config file, edit the file to set tlsCertFile to the location of the certificate
|
||||
file to use to identify this Kubelet, and tlsPrivateKeyFile to the location of the
|
||||
corresponding private key file.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameters in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--tls-cert-file=<path/to/tls-certificate-file>
|
||||
file=<path/to/tls-key-file>
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.14 Edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.15 If using a Kubelet config file, edit the file to set TLSCipherSuites: to TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
If using executable arguments, edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
2.2.5 Run the below command (based on the file location on your system) on the each worker
|
||||
node. For example,
|
||||
chmod 644 /etc/kubernetes/proxy.conf
|
||||
|
||||
2.2.6 Run the below command (based on the file location on your system) on the each worker
|
||||
node. For example,
|
||||
chown root:root /etc/kubernetes/proxy.conf
|
||||
|
||||
2.2.7 Run the following command to modify the file permissions of the --client-ca-file
|
||||
chmod 644 <filename>
|
||||
|
||||
|
||||
== Summary ==
|
||||
15 checks PASS
|
||||
8 checks FAIL
|
||||
2 checks WARN
|
||||
0 checks INFO
|
||||
440
integration/testdata/cis-1.3/job.data
vendored
Normal file
440
integration/testdata/cis-1.3/job.data
vendored
Normal file
@@ -0,0 +1,440 @@
|
||||
[INFO] 1 Master Node Security Configuration
|
||||
[INFO] 1.1 API Server
|
||||
[FAIL] 1.1.1 Ensure that the --anonymous-auth argument is set to false (Scored)
|
||||
[PASS] 1.1.2 Ensure that the --basic-auth-file argument is not set (Scored)
|
||||
[PASS] 1.1.3 Ensure that the --insecure-allow-any-token argument is not set (Scored)
|
||||
[PASS] 1.1.4 Ensure that the --kubelet-https argument is set to true (Scored)
|
||||
[PASS] 1.1.5 Ensure that the --insecure-bind-address argument is not set (Scored)
|
||||
[PASS] 1.1.6 Ensure that the --insecure-port argument is set to 0 (Scored)
|
||||
[PASS] 1.1.7 Ensure that the --secure-port argument is not set to 0 (Scored)
|
||||
[FAIL] 1.1.8 Ensure that the --profiling argument is set to false (Scored)
|
||||
[FAIL] 1.1.9 Ensure that the --repair-malformed-updates argument is set to false (Scored)
|
||||
[PASS] 1.1.10 Ensure that the admission control plugin AlwaysAdmit is not set (Scored)
|
||||
[FAIL] 1.1.11 Ensure that the admission control plugin AlwaysPullImages is set (Scored)
|
||||
[FAIL] 1.1.12 Ensure that the admission control plugin DenyEscalatingExec is set (Scored)
|
||||
[FAIL] 1.1.13 Ensure that the admission control plugin SecurityContextDeny is set (Scored)
|
||||
[PASS] 1.1.14 Ensure that the admission control plugin NamespaceLifecycle is set (Scored)
|
||||
[FAIL] 1.1.15 Ensure that the --audit-log-path argument is set as appropriate (Scored)
|
||||
[FAIL] 1.1.16 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Scored)
|
||||
[FAIL] 1.1.17 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Scored)
|
||||
[FAIL] 1.1.18 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Scored)
|
||||
[PASS] 1.1.19 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 1.1.20 Ensure that the --token-auth-file parameter is not set (Scored)
|
||||
[FAIL] 1.1.21 Ensure that the --kubelet-certificate-authority argument is set as appropriate (Scored)
|
||||
[PASS] 1.1.22 Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Scored)
|
||||
[FAIL] 1.1.23 Ensure that the --service-account-lookup argument is set to true (Scored)
|
||||
[FAIL] 1.1.24 Ensure that the admission control plugin PodSecurityPolicy is set (Scored)
|
||||
[PASS] 1.1.25 Ensure that the --service-account-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.1.26 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored)
|
||||
[FAIL] 1.1.27 Ensure that the admission control plugin ServiceAccount is set(Scored)
|
||||
[PASS] 1.1.28 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.1.29 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[WARN] 1.1.30 Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
[PASS] 1.1.31 Ensure that the --etcd-cafile argument is set as appropriate (Scored)
|
||||
[PASS] 1.1.32 Ensure that the --authorization-mode argument is set to Node (Scored)
|
||||
[PASS] 1.1.33 Ensure that the admission control plugin NodeRestriction is set (Scored)
|
||||
[FAIL] 1.1.34 Ensure that the --experimental-encryption-provider-config argument is set as appropriate (Scored)
|
||||
[WARN] 1.1.35 Ensure that the encryption provider is set to aescbc (Scored)
|
||||
[FAIL] 1.1.36 Ensure that the admission control plugin EventRateLimit is set (Scored)
|
||||
[PASS] 1.1.37a Ensure that the AdvancedAuditing argument is not set to false (Scored)
|
||||
[FAIL] 1.1.37b Ensure that the AdvancedAuditing argument is not set to false (Scored)
|
||||
[PASS] 1.1.38 Ensure that the --request-timeout argument is set as appropriate (Scored)
|
||||
[WARN] 1.1.39 Ensure that the API Server only makes use of Strong Cryptographic Ciphers ( Not Scored)
|
||||
[INFO] 1.2 Scheduler
|
||||
[FAIL] 1.2.1 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.2.2 Ensure that the --address argument is set to 127.0.0.1 (Scored)
|
||||
[INFO] 1.3 Controller Manager
|
||||
[FAIL] 1.3.1 Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.2 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.3.3 Ensure that the --use-service-account-credentials argument is set to true (Scored)
|
||||
[PASS] 1.3.4 Ensure that the --service-account-private-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.3.5 Ensure that the --root-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.6 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[PASS] 1.3.7 Ensure that the --address argument is set to 127.0.0.1 (Scored)
|
||||
[INFO] 1.4 Configuration Files
|
||||
[PASS] 1.4.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.2 Ensure that the API server pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.3 Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.4 Ensure that the controller manager pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.5 Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.6 Ensure that the scheduler pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.7 Ensure that the etcd pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.8 Ensure that the etcd pod specification file ownership is set to root:root (Scored)
|
||||
[WARN] 1.4.9 Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Not Scored)
|
||||
[WARN] 1.4.10 Ensure that the Container Network Interface file ownership is set to root:root (Not Scored)
|
||||
[FAIL] 1.4.11 Ensure that the etcd data directory permissions are set to 700 or more restrictive (Scored)
|
||||
[FAIL] 1.4.12 Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)
|
||||
[PASS] 1.4.13 Ensure that the admin.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.14 Ensure that the admin.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.15 Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.16 Ensure that the scheduler.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.4.17 Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.4.18 Ensure that the controller-manager.conf file ownership is set to root:root (Scored)
|
||||
[INFO] 1.5 etcd
|
||||
[PASS] 1.5.1 Ensure that the --cert-file and --key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.5.2 Ensure that the --client-cert-auth argument is set to true (Scored)
|
||||
[PASS] 1.5.3 Ensure that the --auto-tls argument is not set to true (Scored)
|
||||
[PASS] 1.5.4 Ensure that the --peer-cert-file and --peer-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.5.5 Ensure that the --peer-client-cert-auth argument is set to true (Scored)
|
||||
[PASS] 1.5.6 Ensure that the --peer-auto-tls argument is not set to true (Scored)
|
||||
[WARN] 1.5.7 Ensure that a unique Certificate Authority is used for etcd (Not Scored)
|
||||
[INFO] 1.6 General Security Primitives
|
||||
[WARN] 1.6.1 Ensure that the cluster-admin role is only used where required (Not Scored)
|
||||
[WARN] 1.6.2 Create administrative boundaries between resources using namespaces (Not Scored)
|
||||
[WARN] 1.6.3 Create network segmentation using Network Policies (Not Scored)
|
||||
[WARN] 1.6.4 Ensure that the seccomp profile is set to docker/default in your pod definitions (Not Scored)
|
||||
[WARN] 1.6.5 Apply Security Context to Your Pods and Containers (Not Scored)
|
||||
[WARN] 1.6.6 Configure Image Provenance using ImagePolicyWebhook admission controller (Not Scored)
|
||||
[WARN] 1.6.7 Configure Network policies as appropriate (Not Scored)
|
||||
[WARN] 1.6.8 Place compensating controls in the form of PSP and RBAC for privileged containers usage (Not Scored)
|
||||
[INFO] 1.7 PodSecurityPolicies
|
||||
[WARN] 1.7.1 Do not admit privileged containers (Not Scored)
|
||||
[WARN] 1.7.2 Do not admit containers wishing to share the host process ID namespace (Scored)
|
||||
[WARN] 1.7.3 Do not admit containers wishing to share the host IPC namespace (Scored)
|
||||
[WARN] 1.7.4 Do not admit containers wishing to share the host network namespace (Scored)
|
||||
[WARN] 1.7.5 Do not admit containers with allowPrivilegeEscalation (Scored)
|
||||
[WARN] 1.7.6 Do not admit root containers (Not Scored)
|
||||
[WARN] 1.7.7 Do not admit containers with dangerous capabilities (Not Scored)
|
||||
|
||||
== Remediations ==
|
||||
1.1.1 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
|
||||
1.1.8 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.1.9 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--repair-malformed-updates=false
|
||||
|
||||
1.1.11 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins to
|
||||
include AlwaysPullImages.
|
||||
--enable-admission-plugins=...,AlwaysPullImages,...
|
||||
|
||||
1.1.12 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes DenyEscalatingExec.
|
||||
--enable-admission-plugins=...,DenyEscalatingExec,...
|
||||
|
||||
1.1.13 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to
|
||||
include SecurityContextDeny.
|
||||
--enable-admission-plugins=...,SecurityContextDeny,...
|
||||
|
||||
1.1.15 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-path parameter to a suitable
|
||||
path and file where you would like audit logs to be written, for example:
|
||||
--audit-log-path=/var/log/apiserver/audit.log
|
||||
|
||||
1.1.16 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxage parameter to 30 or
|
||||
as an appropriate number of days: --audit-log-maxage=30
|
||||
|
||||
1.1.17 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxbackup parameter to 10
|
||||
or to an appropriate value.
|
||||
--audit-log-maxbackup=10
|
||||
|
||||
1.1.18 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxsize parameter to an
|
||||
appropriate size in MB. For example, to set it as 100 MB:
|
||||
--audit-log-maxsize=100
|
||||
|
||||
1.1.21 Follow the Kubernetes documentation and setup the TLS connection between the
|
||||
apiserver and kubelets. Then, edit the API server pod specification file
|
||||
/etc/kubernetes/manifests/kube-apiserver.yaml on the master node and set the --kubelet-certificate-authority
|
||||
parameter to the path to the cert file for the certificate authority.
|
||||
--kubelet-certificate-authority=<ca-string>
|
||||
|
||||
1.1.23 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--service-account-lookup=true
|
||||
|
||||
1.1.24 Follow the documentation and create Pod Security Policy objects as per your environment.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes PodSecurityPolicy :
|
||||
--enable-admission-plugins=...,PodSecurityPolicy,...
|
||||
Then restart the API Server.
|
||||
|
||||
1.1.27 Follow the documentation and create ServiceAccount objects as per your environment.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes ServiceAccount.
|
||||
--enable-admission-plugins=...,ServiceAccount,...
|
||||
|
||||
1.1.30 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
1.1.34 Follow the Kubernetes documentation and configure a EncryptionConfig file.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml on the
|
||||
master node and set the --experimental-encryption-provider-config parameter
|
||||
to the path of that file:
|
||||
--experimental-encryption-provider-config=</path/to/EncryptionConfig/File>
|
||||
|
||||
1.1.35 [Manual test]
|
||||
Follow the Kubernetes documentation and configure a EncryptionConfig file. In this file,
|
||||
choose aescbc as the encryption provider.
|
||||
For example,
|
||||
kind: EncryptionConfig
|
||||
apiVersion: v1
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: <32-byte base64-encoded secret>
|
||||
|
||||
1.1.36 Follow the Kubernetes documentation and set the desired limits in a
|
||||
configuration file. Then, edit the API server pod specification file
|
||||
/etc/kubernetes/manifests/kube-apiserver.yaml and set the below parameters.
|
||||
--enable-admission-plugins=...,EventRateLimit,...
|
||||
--admission-control-config-file=<path/to/configuration/file>
|
||||
|
||||
1.1.37b Follow the Kubernetes documentation and set the desired audit policy in the
|
||||
/etc/kubernetes/audit-policy.yaml file. Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
and set the below parameters.
|
||||
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
|
||||
|
||||
1.1.39 Edit the API server pod specification file /etc/kubernetes/manifests
|
||||
kube-apiserver.yaml on the master node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
1.2.1 Edit the Scheduler pod specification file /etc/kubernetes/manifests/kube-scheduler.yaml
|
||||
file on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.3.1 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the --terminated-pod-gc-threshold to an appropriate threshold, for example:
|
||||
--terminated-pod-gc-threshold=10
|
||||
|
||||
1.3.2 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.3.6 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
controller-manager.yaml on the master node and set the --feature-gates parameter to
|
||||
include RotateKubeletServerCertificate=true.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
|
||||
1.4.9 [Manual test]
|
||||
Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod 644 <path/to/cni/files>
|
||||
|
||||
1.4.10 [Manual test]
|
||||
Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chown root:root <path/to/cni/files>
|
||||
|
||||
1.4.11 On the etcd server node, get the etcd data directory, passed as an argument --data-dir ,
|
||||
from the below command:
|
||||
ps -ef | grep etcd
|
||||
Run the below command (based on the etcd data directory found above). For example,
|
||||
chmod 700 /var/lib/etcd
|
||||
|
||||
1.4.12 On the etcd server node, get the etcd data directory, passed as an argument --data-dir ,
|
||||
from the below command:
|
||||
ps -ef | grep etcd
|
||||
Run the below command (based on the etcd data directory found above). For example,
|
||||
chown etcd:etcd /var/lib/etcd
|
||||
|
||||
1.5.7 [Manual test]
|
||||
Follow the etcd documentation and create a dedicated certificate authority setup for the
|
||||
etcd service.
|
||||
Then, edit the etcd pod specification file /etc/kubernetes/manifests/etcd.yaml on the
|
||||
master node and set the below parameter.
|
||||
--trusted-ca-file=</path/to/ca-file>
|
||||
|
||||
1.6.1 [Manual test]
|
||||
Remove any unneeded clusterrolebindings :
|
||||
kubectl delete clusterrolebinding [name]
|
||||
|
||||
1.6.2 [Manual test]
|
||||
Follow the documentation and create namespaces for objects in your deployment as you
|
||||
need them.
|
||||
|
||||
1.6.3 [Manual test]
|
||||
Follow the documentation and create NetworkPolicy objects as you need them.
|
||||
|
||||
1.6.4 [Manual test]
|
||||
Seccomp is an alpha feature currently. By default, all alpha features are disabled. So, you
|
||||
would need to enable alpha features in the apiserver by passing "--feature-
|
||||
gates=AllAlpha=true" argument.
|
||||
Edit the /etc/kubernetes/manifests/kube-apiserver.yaml file on the master node and set the KUBE_API_ARGS
|
||||
parameter to "--feature-gates=AllAlpha=true"
|
||||
KUBE_API_ARGS="--feature-gates=AllAlpha=true"
|
||||
Based on your system, restart the kube-apiserver service. For example:
|
||||
systemctl restart kube-apiserver.service
|
||||
Use annotations to enable the docker/default seccomp profile in your pod definitions. An
|
||||
example is as below:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: trustworthy-pod
|
||||
annotations:
|
||||
seccomp.security.alpha.kubernetes.io/pod: docker/default
|
||||
spec:
|
||||
containers:
|
||||
- name: trustworthy-container
|
||||
image: sotrustworthy:latest
|
||||
|
||||
1.6.5 [Manual test]
|
||||
Follow the Kubernetes documentation and apply security contexts to your pods. For a
|
||||
suggested list of security contexts, you may refer to the CIS Security Benchmark for Docker
|
||||
Containers.
|
||||
|
||||
1.6.6 [Manual test]
|
||||
Follow the Kubernetes documentation and setup image provenance.
|
||||
|
||||
1.6.7 [Manual test]
|
||||
Follow the Kubernetes documentation and setup network policies as appropriate.
|
||||
For example, you could create a "default" isolation policy for a Namespace by creating a
|
||||
NetworkPolicy that selects all pods but does not allow any traffic:
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: default-deny
|
||||
spec:
|
||||
podSelector:
|
||||
|
||||
1.6.8 [Manual test]
|
||||
Follow Kubernetes documentation and setup PSP and RBAC authorization for your cluster.
|
||||
|
||||
1.7.1 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.privileged field is omitted or set to false.
|
||||
|
||||
1.7.2 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.hostPID field is omitted or set to false.
|
||||
|
||||
1.7.3 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.hostIPC field is omitted or set to false.
|
||||
|
||||
1.7.4 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.hostNetwork field is omitted or set to false.
|
||||
|
||||
1.7.5 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.allowPrivilegeEscalation field is omitted or set to false.
|
||||
|
||||
1.7.6 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.runAsUser.rule is set to either MustRunAsNonRoot or MustRunAs with the range of UIDs not including 0.
|
||||
|
||||
1.7.7 [Manual test]
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the .spec.requiredDropCapabilities is set to include either NET_RAW or ALL.
|
||||
|
||||
|
||||
== Summary ==
|
||||
45 checks PASS
|
||||
23 checks FAIL
|
||||
21 checks WARN
|
||||
0 checks INFO
|
||||
[INFO] 2 Worker Node Security Configuration
|
||||
[INFO] 2.1 Kubelet
|
||||
[FAIL] 2.1.1 Ensure that the --allow-privileged argument is set to false (Scored)
|
||||
[PASS] 2.1.2 Ensure that the --anonymous-auth argument is set to false (Scored)
|
||||
[PASS] 2.1.3 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 2.1.4 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 2.1.5 Ensure that the --read-only-port argument is set to 0 (Scored)
|
||||
[PASS] 2.1.6 Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)
|
||||
[FAIL] 2.1.7 Ensure that the --protect-kernel-defaults argument is set to true (Scored)
|
||||
[PASS] 2.1.8 Ensure that the --make-iptables-util-chains argument is set to true (Scored)
|
||||
[PASS] 2.1.9 Ensure that the --hostname-override argument is not set (Scored)
|
||||
[FAIL] 2.1.10 Ensure that the --event-qps argument is set to 0 (Scored)
|
||||
[FAIL] 2.1.11 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 2.1.12 Ensure that the --cadvisor-port argument is set to 0 (Scored)
|
||||
[PASS] 2.1.13 Ensure that the --rotate-certificates argument is not set to false (Scored)
|
||||
[FAIL] 2.1.14 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[WARN] 2.1.15 Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
[INFO] 2.2 Configuration Files
|
||||
[PASS] 2.2.1 Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 2.2.2 Ensure that the kubelet.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 2.2.3 Ensure that the kubelet service file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 2.2.4 Ensure that the kubelet service file ownership is set to root:root (Scored)
|
||||
[FAIL] 2.2.5 Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)
|
||||
[FAIL] 2.2.6 Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)
|
||||
[WARN] 2.2.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 2.2.8 Ensure that the client certificate authorities file ownership is set to root:root (Scored)
|
||||
[PASS] 2.2.9 Ensure that the kubelet configuration file ownership is set to root:root (Scored)
|
||||
[PASS] 2.2.10 Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)
|
||||
|
||||
== Remediations ==
|
||||
2.1.1 Edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
on each worker node and set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--allow-privileged=false
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.5 If using a Kubelet config file, edit the file to set readOnlyPort to 0 .
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--read-only-port=0
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.7 If using a Kubelet config file, edit the file to set protectKernelDefaults: true .
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--protect-kernel-defaults=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.10 If using a Kubelet config file, edit the file to set eventRecordQPS: 0 .
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--event-qps=0
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.11 If using a Kubelet config file, edit the file to set tlsCertFile to the location of the certificate
|
||||
file to use to identify this Kubelet, and tlsPrivateKeyFile to the location of the
|
||||
corresponding private key file.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameters in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--tls-cert-file=<path/to/tls-certificate-file>
|
||||
file=<path/to/tls-key-file>
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.14 Edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
2.1.15 If using a Kubelet config file, edit the file to set TLSCipherSuites: to TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
If using executable arguments, edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
2.2.5 Run the below command (based on the file location on your system) on the each worker
|
||||
node. For example,
|
||||
chmod 644 /etc/kubernetes/proxy.conf
|
||||
|
||||
2.2.6 Run the below command (based on the file location on your system) on the each worker
|
||||
node. For example,
|
||||
chown root:root /etc/kubernetes/proxy.conf
|
||||
|
||||
2.2.7 Run the following command to modify the file permissions of the --client-ca-file
|
||||
chmod 644 <filename>
|
||||
|
||||
|
||||
== Summary ==
|
||||
15 checks PASS
|
||||
8 checks FAIL
|
||||
2 checks WARN
|
||||
0 checks INFO
|
||||
19
integration/testdata/cis-1.5/add-tls-kind.yaml
vendored
Normal file
19
integration/testdata/cis-1.5/add-tls-kind.yaml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
apiVersion: kind.sigs.k8s.io/v1alpha3
|
||||
kind: Cluster
|
||||
networking:
|
||||
apiServerAddress: "0.0.0.0"
|
||||
|
||||
kubeadmConfigPatchesJson6902:
|
||||
- group: kubelet.config.k8s.io
|
||||
version: v1beta1
|
||||
kind: KubeletConfiguration
|
||||
patch: |
|
||||
- op: add
|
||||
path: /tlsCipherSuites
|
||||
value: ["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"]
|
||||
|
||||
nodes:
|
||||
# the control plane node config
|
||||
- role: control-plane
|
||||
image: "kindest/node:v1.18.0"
|
||||
188
integration/testdata/cis-1.5/job-master.data
vendored
Normal file
188
integration/testdata/cis-1.5/job-master.data
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
[INFO] 1 Master Node Security Configuration
|
||||
[INFO] 1.1 Master Node Configuration Files
|
||||
[PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.2 Ensure that the API server pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.3 Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.4 Ensure that the controller manager pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.5 Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.6 Ensure that the scheduler pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.7 Ensure that the etcd pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.8 Ensure that the etcd pod specification file ownership is set to root:root (Scored)
|
||||
[WARN] 1.1.9 Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Not Scored)
|
||||
[WARN] 1.1.10 Ensure that the Container Network Interface file ownership is set to root:root (Not Scored)
|
||||
[PASS] 1.1.11 Ensure that the etcd data directory permissions are set to 700 or more restrictive (Scored)
|
||||
[FAIL] 1.1.12 Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)
|
||||
[PASS] 1.1.13 Ensure that the admin.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.14 Ensure that the admin.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.15 Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.16 Ensure that the scheduler.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.17 Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.18 Ensure that the controller-manager.conf file ownership is set to root:root (Scored)
|
||||
[WARN] 1.1.19 Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Scored)
|
||||
[WARN] 1.1.20 Ensure that the Kubernetes PKI certificate file permissions are set to 644 or more restrictive (Scored)
|
||||
[WARN] 1.1.21 Ensure that the Kubernetes PKI key file permissions are set to 600 (Scored)
|
||||
[INFO] 1.2 API Server
|
||||
[WARN] 1.2.1 Ensure that the --anonymous-auth argument is set to false (Not Scored)
|
||||
[PASS] 1.2.2 Ensure that the --basic-auth-file argument is not set (Scored)
|
||||
[PASS] 1.2.3 Ensure that the --token-auth-file parameter is not set (Scored)
|
||||
[PASS] 1.2.4 Ensure that the --kubelet-https argument is set to true (Scored)
|
||||
[PASS] 1.2.5 Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Scored)
|
||||
[FAIL] 1.2.6 Ensure that the --kubelet-certificate-authority argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.7 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 1.2.8 Ensure that the --authorization-mode argument includes Node (Scored)
|
||||
[PASS] 1.2.9 Ensure that the --authorization-mode argument includes RBAC (Scored)
|
||||
[WARN] 1.2.10 Ensure that the admission control plugin EventRateLimit is set (Not Scored)
|
||||
[PASS] 1.2.11 Ensure that the admission control plugin AlwaysAdmit is not set (Scored)
|
||||
[WARN] 1.2.12 Ensure that the admission control plugin AlwaysPullImages is set (Not Scored)
|
||||
[WARN] 1.2.13 Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used (Not Scored)
|
||||
[PASS] 1.2.14 Ensure that the admission control plugin ServiceAccount is set (Scored)
|
||||
[PASS] 1.2.15 Ensure that the admission control plugin NamespaceLifecycle is set (Scored)
|
||||
[FAIL] 1.2.16 Ensure that the admission control plugin PodSecurityPolicy is set (Scored)
|
||||
[PASS] 1.2.17 Ensure that the admission control plugin NodeRestriction is set (Scored)
|
||||
[PASS] 1.2.18 Ensure that the --insecure-bind-address argument is not set (Scored)
|
||||
[PASS] 1.2.19 Ensure that the --insecure-port argument is set to 0 (Scored)
|
||||
[PASS] 1.2.20 Ensure that the --secure-port argument is not set to 0 (Scored)
|
||||
[FAIL] 1.2.21 Ensure that the --profiling argument is set to false (Scored)
|
||||
[FAIL] 1.2.22 Ensure that the --audit-log-path argument is set (Scored)
|
||||
[FAIL] 1.2.23 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Scored)
|
||||
[FAIL] 1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Scored)
|
||||
[FAIL] 1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Scored)
|
||||
[PASS] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.27 Ensure that the --service-account-lookup argument is set to true (Scored)
|
||||
[PASS] 1.2.28 Ensure that the --service-account-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored)
|
||||
[PASS] 1.2.30 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.2.31 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.32 Ensure that the --etcd-cafile argument is set as appropriate (Scored)
|
||||
[FAIL] 1.2.33 Ensure that the --encryption-provider-config argument is set as appropriate (Scored)
|
||||
[WARN] 1.2.34 Ensure that encryption providers are appropriately configured (Scored)
|
||||
[WARN] 1.2.35 Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
[INFO] 1.3 Controller Manager
|
||||
[FAIL] 1.3.1 Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.2 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.3.3 Ensure that the --use-service-account-credentials argument is set to true (Scored)
|
||||
[PASS] 1.3.4 Ensure that the --service-account-private-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.3.5 Ensure that the --root-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.6 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[PASS] 1.3.7 Ensure that the --bind-address argument is set to 127.0.0.1 (Scored)
|
||||
[INFO] 1.4 Scheduler
|
||||
[FAIL] 1.4.1 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.4.2 Ensure that the --bind-address argument is set to 127.0.0.1 (Scored)
|
||||
|
||||
== Remediations ==
|
||||
1.1.9 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod 644 <path/to/cni/files>
|
||||
|
||||
1.1.10 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chown root:root <path/to/cni/files>
|
||||
|
||||
1.1.12 On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
|
||||
from the below command:
|
||||
ps -ef | grep etcd
|
||||
Run the below command (based on the etcd data directory found above).
|
||||
For example, chown etcd:etcd /var/lib/etcd
|
||||
|
||||
1.1.19 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chown -R root:root /etc/kubernetes/pki/
|
||||
|
||||
1.1.20 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod -R 644 /etc/kubernetes/pki/*.crt
|
||||
|
||||
1.1.21 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod -R 600 /etc/kubernetes/pki/*.key
|
||||
|
||||
1.2.1 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
|
||||
1.2.6 Follow the Kubernetes documentation and setup the TLS connection between
|
||||
the apiserver and kubelets. Then, edit the API server pod specification file
|
||||
/etc/kubernetes/manifests/kube-apiserver.yaml on the master node and set the
|
||||
--kubelet-certificate-authority parameter to the path to the cert file for the certificate authority.
|
||||
--kubelet-certificate-authority=<ca-string>
|
||||
|
||||
1.2.10 Follow the Kubernetes documentation and set the desired limits in a configuration file.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
and set the below parameters.
|
||||
--enable-admission-plugins=...,EventRateLimit,...
|
||||
--admission-control-config-file=<path/to/configuration/file>
|
||||
|
||||
1.2.12 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to include
|
||||
AlwaysPullImages.
|
||||
--enable-admission-plugins=...,AlwaysPullImages,...
|
||||
|
||||
1.2.13 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to include
|
||||
SecurityContextDeny, unless PodSecurityPolicy is already in place.
|
||||
--enable-admission-plugins=...,SecurityContextDeny,...
|
||||
|
||||
1.2.16 Follow the documentation and create Pod Security Policy objects as per your environment.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes PodSecurityPolicy:
|
||||
--enable-admission-plugins=...,PodSecurityPolicy,...
|
||||
Then restart the API Server.
|
||||
|
||||
1.2.21 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.2.22 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-path parameter to a suitable path and
|
||||
file where you would like audit logs to be written, for example:
|
||||
--audit-log-path=/var/log/apiserver/audit.log
|
||||
|
||||
1.2.23 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxage parameter to 30 or as an appropriate number of days:
|
||||
--audit-log-maxage=30
|
||||
|
||||
1.2.24 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxbackup parameter to 10 or to an appropriate
|
||||
value.
|
||||
--audit-log-maxbackup=10
|
||||
|
||||
1.2.25 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxsize parameter to an appropriate size in MB.
|
||||
For example, to set it as 100 MB:
|
||||
--audit-log-maxsize=100
|
||||
|
||||
1.2.33 Follow the Kubernetes documentation and configure a EncryptionConfig file.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --encryption-provider-config parameter to the path of that file: --encryption-provider-config=</path/to/EncryptionConfig/File>
|
||||
|
||||
1.2.34 Follow the Kubernetes documentation and configure a EncryptionConfig file.
|
||||
In this file, choose aescbc, kms or secretbox as the encryption provider.
|
||||
|
||||
1.2.35 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
1.3.1 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the --terminated-pod-gc-threshold to an appropriate threshold,
|
||||
for example:
|
||||
--terminated-pod-gc-threshold=10
|
||||
|
||||
1.3.2 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.3.6 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the --feature-gates parameter to include RotateKubeletServerCertificate=true.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
|
||||
1.4.1 Edit the Scheduler pod specification file /etc/kubernetes/manifests/kube-scheduler.yaml file
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
|
||||
== Summary ==
|
||||
41 checks PASS
|
||||
13 checks FAIL
|
||||
11 checks WARN
|
||||
0 checks INFO
|
||||
87
integration/testdata/cis-1.5/job-node.data
vendored
Normal file
87
integration/testdata/cis-1.5/job-node.data
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
[INFO] 4 Worker Node Security Configuration
|
||||
[INFO] 4.1 Worker Node Configuration Files
|
||||
[PASS] 4.1.1 Ensure that the kubelet service file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.2 Ensure that the kubelet service file ownership is set to root:root (Scored)
|
||||
[FAIL] 4.1.3 Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)
|
||||
[FAIL] 4.1.4 Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)
|
||||
[PASS] 4.1.5 Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.6 Ensure that the kubelet.conf file ownership is set to root:root (Scored)
|
||||
[WARN] 4.1.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.8 Ensure that the client certificate authorities file ownership is set to root:root (Scored)
|
||||
[PASS] 4.1.9 Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.10 Ensure that the kubelet configuration file ownership is set to root:root (Scored)
|
||||
[INFO] 4.2 Kubelet
|
||||
[PASS] 4.2.1 Ensure that the --anonymous-auth argument is set to false (Scored)
|
||||
[PASS] 4.2.2 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 4.2.3 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 4.2.4 Ensure that the --read-only-port argument is set to 0 (Scored)
|
||||
[PASS] 4.2.5 Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)
|
||||
[FAIL] 4.2.6 Ensure that the --protect-kernel-defaults argument is set to true (Scored)
|
||||
[PASS] 4.2.7 Ensure that the --make-iptables-util-chains argument is set to true (Scored)
|
||||
[PASS] 4.2.8 Ensure that the --hostname-override argument is not set (Not Scored)
|
||||
[WARN] 4.2.9 Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture (Not Scored)
|
||||
[FAIL] 4.2.10 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 4.2.11 Ensure that the --rotate-certificates argument is not set to false (Scored)
|
||||
[FAIL] 4.2.12 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[PASS] 4.2.13 Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
|
||||
== Remediations ==
|
||||
4.1.3 Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example,
|
||||
chmod 644 /etc/kubernetes/proxy.conf
|
||||
|
||||
4.1.4 Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example, chown root:root /etc/kubernetes/proxy.conf
|
||||
|
||||
4.1.7 audit test did not run: There are no tests
|
||||
4.2.4 If using a Kubelet config file, edit the file to set readOnlyPort to 0.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--read-only-port=0
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.6 If using a Kubelet config file, edit the file to set protectKernelDefaults: true.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--protect-kernel-defaults=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.9 If using a Kubelet config file, edit the file to set eventRecordQPS: to an appropriate level.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.10 If using a Kubelet config file, edit the file to set tlsCertFile to the location
|
||||
of the certificate file to use to identify this Kubelet, and tlsPrivateKeyFile
|
||||
to the location of the corresponding private key file.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameters in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--tls-cert-file=<path/to/tls-certificate-file>
|
||||
--tls-private-key-file=<path/to/tls-key-file>
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.12 Edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
|
||||
== Summary ==
|
||||
15 checks PASS
|
||||
6 checks FAIL
|
||||
2 checks WARN
|
||||
0 checks INFO
|
||||
446
integration/testdata/cis-1.5/job.data
vendored
Normal file
446
integration/testdata/cis-1.5/job.data
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
[INFO] 1 Master Node Security Configuration
|
||||
[INFO] 1.1 Master Node Configuration Files
|
||||
[PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.2 Ensure that the API server pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.3 Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.4 Ensure that the controller manager pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.5 Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.6 Ensure that the scheduler pod specification file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.7 Ensure that the etcd pod specification file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.8 Ensure that the etcd pod specification file ownership is set to root:root (Scored)
|
||||
[WARN] 1.1.9 Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Not Scored)
|
||||
[WARN] 1.1.10 Ensure that the Container Network Interface file ownership is set to root:root (Not Scored)
|
||||
[PASS] 1.1.11 Ensure that the etcd data directory permissions are set to 700 or more restrictive (Scored)
|
||||
[FAIL] 1.1.12 Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)
|
||||
[PASS] 1.1.13 Ensure that the admin.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.14 Ensure that the admin.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.15 Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.16 Ensure that the scheduler.conf file ownership is set to root:root (Scored)
|
||||
[PASS] 1.1.17 Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 1.1.18 Ensure that the controller-manager.conf file ownership is set to root:root (Scored)
|
||||
[WARN] 1.1.19 Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Scored)
|
||||
[WARN] 1.1.20 Ensure that the Kubernetes PKI certificate file permissions are set to 644 or more restrictive (Scored)
|
||||
[WARN] 1.1.21 Ensure that the Kubernetes PKI key file permissions are set to 600 (Scored)
|
||||
[INFO] 1.2 API Server
|
||||
[WARN] 1.2.1 Ensure that the --anonymous-auth argument is set to false (Not Scored)
|
||||
[PASS] 1.2.2 Ensure that the --basic-auth-file argument is not set (Scored)
|
||||
[PASS] 1.2.3 Ensure that the --token-auth-file parameter is not set (Scored)
|
||||
[PASS] 1.2.4 Ensure that the --kubelet-https argument is set to true (Scored)
|
||||
[PASS] 1.2.5 Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Scored)
|
||||
[FAIL] 1.2.6 Ensure that the --kubelet-certificate-authority argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.7 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 1.2.8 Ensure that the --authorization-mode argument includes Node (Scored)
|
||||
[PASS] 1.2.9 Ensure that the --authorization-mode argument includes RBAC (Scored)
|
||||
[WARN] 1.2.10 Ensure that the admission control plugin EventRateLimit is set (Not Scored)
|
||||
[PASS] 1.2.11 Ensure that the admission control plugin AlwaysAdmit is not set (Scored)
|
||||
[WARN] 1.2.12 Ensure that the admission control plugin AlwaysPullImages is set (Not Scored)
|
||||
[WARN] 1.2.13 Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used (Not Scored)
|
||||
[PASS] 1.2.14 Ensure that the admission control plugin ServiceAccount is set (Scored)
|
||||
[PASS] 1.2.15 Ensure that the admission control plugin NamespaceLifecycle is set (Scored)
|
||||
[FAIL] 1.2.16 Ensure that the admission control plugin PodSecurityPolicy is set (Scored)
|
||||
[PASS] 1.2.17 Ensure that the admission control plugin NodeRestriction is set (Scored)
|
||||
[PASS] 1.2.18 Ensure that the --insecure-bind-address argument is not set (Scored)
|
||||
[PASS] 1.2.19 Ensure that the --insecure-port argument is set to 0 (Scored)
|
||||
[PASS] 1.2.20 Ensure that the --secure-port argument is not set to 0 (Scored)
|
||||
[FAIL] 1.2.21 Ensure that the --profiling argument is set to false (Scored)
|
||||
[FAIL] 1.2.22 Ensure that the --audit-log-path argument is set (Scored)
|
||||
[FAIL] 1.2.23 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Scored)
|
||||
[FAIL] 1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Scored)
|
||||
[FAIL] 1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Scored)
|
||||
[PASS] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.27 Ensure that the --service-account-lookup argument is set to true (Scored)
|
||||
[PASS] 1.2.28 Ensure that the --service-account-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored)
|
||||
[PASS] 1.2.30 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 1.2.31 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.2.32 Ensure that the --etcd-cafile argument is set as appropriate (Scored)
|
||||
[FAIL] 1.2.33 Ensure that the --encryption-provider-config argument is set as appropriate (Scored)
|
||||
[WARN] 1.2.34 Ensure that encryption providers are appropriately configured (Scored)
|
||||
[WARN] 1.2.35 Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
[INFO] 1.3 Controller Manager
|
||||
[FAIL] 1.3.1 Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.2 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.3.3 Ensure that the --use-service-account-credentials argument is set to true (Scored)
|
||||
[PASS] 1.3.4 Ensure that the --service-account-private-key-file argument is set as appropriate (Scored)
|
||||
[PASS] 1.3.5 Ensure that the --root-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 1.3.6 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[PASS] 1.3.7 Ensure that the --bind-address argument is set to 127.0.0.1 (Scored)
|
||||
[INFO] 1.4 Scheduler
|
||||
[FAIL] 1.4.1 Ensure that the --profiling argument is set to false (Scored)
|
||||
[PASS] 1.4.2 Ensure that the --bind-address argument is set to 127.0.0.1 (Scored)
|
||||
|
||||
== Remediations ==
|
||||
1.1.9 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod 644 <path/to/cni/files>
|
||||
|
||||
1.1.10 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chown root:root <path/to/cni/files>
|
||||
|
||||
1.1.12 On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
|
||||
from the below command:
|
||||
ps -ef | grep etcd
|
||||
Run the below command (based on the etcd data directory found above).
|
||||
For example, chown etcd:etcd /var/lib/etcd
|
||||
|
||||
1.1.19 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chown -R root:root /etc/kubernetes/pki/
|
||||
|
||||
1.1.20 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod -R 644 /etc/kubernetes/pki/*.crt
|
||||
|
||||
1.1.21 Run the below command (based on the file location on your system) on the master node.
|
||||
For example,
|
||||
chmod -R 600 /etc/kubernetes/pki/*.key
|
||||
|
||||
1.2.1 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
|
||||
1.2.6 Follow the Kubernetes documentation and setup the TLS connection between
|
||||
the apiserver and kubelets. Then, edit the API server pod specification file
|
||||
/etc/kubernetes/manifests/kube-apiserver.yaml on the master node and set the
|
||||
--kubelet-certificate-authority parameter to the path to the cert file for the certificate authority.
|
||||
--kubelet-certificate-authority=<ca-string>
|
||||
|
||||
1.2.10 Follow the Kubernetes documentation and set the desired limits in a configuration file.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
and set the below parameters.
|
||||
--enable-admission-plugins=...,EventRateLimit,...
|
||||
--admission-control-config-file=<path/to/configuration/file>
|
||||
|
||||
1.2.12 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to include
|
||||
AlwaysPullImages.
|
||||
--enable-admission-plugins=...,AlwaysPullImages,...
|
||||
|
||||
1.2.13 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to include
|
||||
SecurityContextDeny, unless PodSecurityPolicy is already in place.
|
||||
--enable-admission-plugins=...,SecurityContextDeny,...
|
||||
|
||||
1.2.16 Follow the documentation and create Pod Security Policy objects as per your environment.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --enable-admission-plugins parameter to a
|
||||
value that includes PodSecurityPolicy:
|
||||
--enable-admission-plugins=...,PodSecurityPolicy,...
|
||||
Then restart the API Server.
|
||||
|
||||
1.2.21 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.2.22 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-path parameter to a suitable path and
|
||||
file where you would like audit logs to be written, for example:
|
||||
--audit-log-path=/var/log/apiserver/audit.log
|
||||
|
||||
1.2.23 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxage parameter to 30 or as an appropriate number of days:
|
||||
--audit-log-maxage=30
|
||||
|
||||
1.2.24 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxbackup parameter to 10 or to an appropriate
|
||||
value.
|
||||
--audit-log-maxbackup=10
|
||||
|
||||
1.2.25 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --audit-log-maxsize parameter to an appropriate size in MB.
|
||||
For example, to set it as 100 MB:
|
||||
--audit-log-maxsize=100
|
||||
|
||||
1.2.33 Follow the Kubernetes documentation and configure a EncryptionConfig file.
|
||||
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the --encryption-provider-config parameter to the path of that file: --encryption-provider-config=</path/to/EncryptionConfig/File>
|
||||
|
||||
1.2.34 Follow the Kubernetes documentation and configure a EncryptionConfig file.
|
||||
In this file, choose aescbc, kms or secretbox as the encryption provider.
|
||||
|
||||
1.2.35 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the master node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
1.3.1 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the --terminated-pod-gc-threshold to an appropriate threshold,
|
||||
for example:
|
||||
--terminated-pod-gc-threshold=10
|
||||
|
||||
1.3.2 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
1.3.6 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
|
||||
on the master node and set the --feature-gates parameter to include RotateKubeletServerCertificate=true.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
|
||||
1.4.1 Edit the Scheduler pod specification file /etc/kubernetes/manifests/kube-scheduler.yaml file
|
||||
on the master node and set the below parameter.
|
||||
--profiling=false
|
||||
|
||||
|
||||
== Summary ==
|
||||
41 checks PASS
|
||||
13 checks FAIL
|
||||
11 checks WARN
|
||||
0 checks INFO
|
||||
[INFO] 2 Etcd Node Configuration
|
||||
[INFO] 2 Etcd Node Configuration Files
|
||||
[PASS] 2.1 Ensure that the --cert-file and --key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 2.2 Ensure that the --client-cert-auth argument is set to true (Scored)
|
||||
[PASS] 2.3 Ensure that the --auto-tls argument is not set to true (Scored)
|
||||
[PASS] 2.4 Ensure that the --peer-cert-file and --peer-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 2.5 Ensure that the --peer-client-cert-auth argument is set to true (Scored)
|
||||
[PASS] 2.6 Ensure that the --peer-auto-tls argument is not set to true (Scored)
|
||||
[PASS] 2.7 Ensure that a unique Certificate Authority is used for etcd (Not Scored)
|
||||
|
||||
== Summary ==
|
||||
7 checks PASS
|
||||
0 checks FAIL
|
||||
0 checks WARN
|
||||
0 checks INFO
|
||||
[INFO] 3 Control Plane Configuration
|
||||
[INFO] 3.1 Authentication and Authorization
|
||||
[WARN] 3.1.1 Client certificate authentication should not be used for users (Not Scored)
|
||||
[INFO] 3.2 Logging
|
||||
[WARN] 3.2.1 Ensure that a minimal audit policy is created (Scored)
|
||||
[WARN] 3.2.2 Ensure that the audit policy covers key security concerns (Not Scored)
|
||||
|
||||
== Remediations ==
|
||||
3.1.1 Alternative mechanisms provided by Kubernetes such as the use of OIDC should be
|
||||
implemented in place of client certificates.
|
||||
|
||||
3.2.1 Create an audit policy file for your cluster.
|
||||
|
||||
3.2.2 Consider modification of the audit policy in use on the cluster to include these items, at a
|
||||
minimum.
|
||||
|
||||
|
||||
== Summary ==
|
||||
0 checks PASS
|
||||
0 checks FAIL
|
||||
3 checks WARN
|
||||
0 checks INFO
|
||||
[INFO] 4 Worker Node Security Configuration
|
||||
[INFO] 4.1 Worker Node Configuration Files
|
||||
[PASS] 4.1.1 Ensure that the kubelet service file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.2 Ensure that the kubelet service file ownership is set to root:root (Scored)
|
||||
[FAIL] 4.1.3 Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)
|
||||
[FAIL] 4.1.4 Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)
|
||||
[PASS] 4.1.5 Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.6 Ensure that the kubelet.conf file ownership is set to root:root (Scored)
|
||||
[WARN] 4.1.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.8 Ensure that the client certificate authorities file ownership is set to root:root (Scored)
|
||||
[PASS] 4.1.9 Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)
|
||||
[PASS] 4.1.10 Ensure that the kubelet configuration file ownership is set to root:root (Scored)
|
||||
[INFO] 4.2 Kubelet
|
||||
[PASS] 4.2.1 Ensure that the --anonymous-auth argument is set to false (Scored)
|
||||
[PASS] 4.2.2 Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)
|
||||
[PASS] 4.2.3 Ensure that the --client-ca-file argument is set as appropriate (Scored)
|
||||
[FAIL] 4.2.4 Ensure that the --read-only-port argument is set to 0 (Scored)
|
||||
[PASS] 4.2.5 Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)
|
||||
[FAIL] 4.2.6 Ensure that the --protect-kernel-defaults argument is set to true (Scored)
|
||||
[PASS] 4.2.7 Ensure that the --make-iptables-util-chains argument is set to true (Scored)
|
||||
[PASS] 4.2.8 Ensure that the --hostname-override argument is not set (Not Scored)
|
||||
[WARN] 4.2.9 Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture (Not Scored)
|
||||
[FAIL] 4.2.10 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)
|
||||
[PASS] 4.2.11 Ensure that the --rotate-certificates argument is not set to false (Scored)
|
||||
[FAIL] 4.2.12 Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)
|
||||
[PASS] 4.2.13 Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)
|
||||
|
||||
== Remediations ==
|
||||
4.1.3 Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example,
|
||||
chmod 644 /etc/kubernetes/proxy.conf
|
||||
|
||||
4.1.4 Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example, chown root:root /etc/kubernetes/proxy.conf
|
||||
|
||||
4.1.7 audit test did not run: There are no tests
|
||||
4.2.4 If using a Kubelet config file, edit the file to set readOnlyPort to 0.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--read-only-port=0
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.6 If using a Kubelet config file, edit the file to set protectKernelDefaults: true.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
--protect-kernel-defaults=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.9 If using a Kubelet config file, edit the file to set eventRecordQPS: to an appropriate level.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.10 If using a Kubelet config file, edit the file to set tlsCertFile to the location
|
||||
of the certificate file to use to identify this Kubelet, and tlsPrivateKeyFile
|
||||
to the location of the corresponding private key file.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf on each worker node and
|
||||
set the below parameters in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--tls-cert-file=<path/to/tls-certificate-file>
|
||||
--tls-private-key-file=<path/to/tls-key-file>
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
4.2.12 Edit the kubelet service file /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
|
||||
|
||||
== Summary ==
|
||||
15 checks PASS
|
||||
6 checks FAIL
|
||||
2 checks WARN
|
||||
0 checks INFO
|
||||
[INFO] 5 Kubernetes Policies
|
||||
[INFO] 5.1 RBAC and Service Accounts
|
||||
[WARN] 5.1.1 Ensure that the cluster-admin role is only used where required (Not Scored)
|
||||
[WARN] 5.1.2 Minimize access to secrets (Not Scored)
|
||||
[WARN] 5.1.3 Minimize wildcard use in Roles and ClusterRoles (Not Scored)
|
||||
[WARN] 5.1.4 Minimize access to create pods (Not Scored)
|
||||
[WARN] 5.1.5 Ensure that default service accounts are not actively used. (Scored)
|
||||
[WARN] 5.1.6 Ensure that Service Account Tokens are only mounted where necessary (Not Scored)
|
||||
[INFO] 5.2 Pod Security Policies
|
||||
[WARN] 5.2.1 Minimize the admission of privileged containers (Not Scored)
|
||||
[WARN] 5.2.2 Minimize the admission of containers wishing to share the host process ID namespace (Scored)
|
||||
[WARN] 5.2.3 Minimize the admission of containers wishing to share the host IPC namespace (Scored)
|
||||
[WARN] 5.2.4 Minimize the admission of containers wishing to share the host network namespace (Scored)
|
||||
[WARN] 5.2.5 Minimize the admission of containers with allowPrivilegeEscalation (Scored)
|
||||
[WARN] 5.2.6 Minimize the admission of root containers (Not Scored)
|
||||
[WARN] 5.2.7 Minimize the admission of containers with the NET_RAW capability (Not Scored)
|
||||
[WARN] 5.2.8 Minimize the admission of containers with added capabilities (Not Scored)
|
||||
[WARN] 5.2.9 Minimize the admission of containers with capabilities assigned (Not Scored)
|
||||
[INFO] 5.3 Network Policies and CNI
|
||||
[WARN] 5.3.1 Ensure that the CNI in use supports Network Policies (Not Scored)
|
||||
[WARN] 5.3.2 Ensure that all Namespaces have Network Policies defined (Scored)
|
||||
[INFO] 5.4 Secrets Management
|
||||
[WARN] 5.4.1 Prefer using secrets as files over secrets as environment variables (Not Scored)
|
||||
[WARN] 5.4.2 Consider external secret storage (Not Scored)
|
||||
[INFO] 5.5 Extensible Admission Control
|
||||
[WARN] 5.5.1 Configure Image Provenance using ImagePolicyWebhook admission controller (Not Scored)
|
||||
[INFO] 5.6 General Policies
|
||||
[WARN] 5.6.1 Create administrative boundaries between resources using namespaces (Not Scored)
|
||||
[WARN] 5.6.2 Ensure that the seccomp profile is set to docker/default in your pod definitions (Not Scored)
|
||||
[WARN] 5.6.3 Apply Security Context to Your Pods and Containers (Not Scored)
|
||||
[WARN] 5.6.4 The default namespace should not be used (Scored)
|
||||
|
||||
== Remediations ==
|
||||
5.1.1 Identify all clusterrolebindings to the cluster-admin role. Check if they are used and
|
||||
if they need this role or if they could use a role with fewer privileges.
|
||||
Where possible, first bind users to a lower privileged role and then remove the
|
||||
clusterrolebinding to the cluster-admin role :
|
||||
kubectl delete clusterrolebinding [name]
|
||||
|
||||
5.1.2 Where possible, remove get, list and watch access to secret objects in the cluster.
|
||||
|
||||
5.1.3 Where possible replace any use of wildcards in clusterroles and roles with specific
|
||||
objects or actions.
|
||||
|
||||
5.1.4 Where possible, remove create access to pod objects in the cluster.
|
||||
|
||||
5.1.5 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
|
||||
|
||||
5.1.6 Modify the definition of pods and service accounts which do not need to mount service
|
||||
account tokens to disable it.
|
||||
|
||||
5.2.1 Create a PSP as described in the Kubernetes documentation, ensuring that
|
||||
the .spec.privileged field is omitted or set to false.
|
||||
|
||||
5.2.2 Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostPID field is omitted or set to false.
|
||||
|
||||
5.2.3 Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostIPC field is omitted or set to false.
|
||||
|
||||
5.2.4 Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostNetwork field is omitted or set to false.
|
||||
|
||||
5.2.5 Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.allowPrivilegeEscalation field is omitted or set to false.
|
||||
|
||||
5.2.6 Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.runAsUser.rule is set to either MustRunAsNonRoot or MustRunAs with the range of
|
||||
UIDs not including 0.
|
||||
|
||||
5.2.7 Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.requiredDropCapabilities is set to include either NET_RAW or ALL.
|
||||
|
||||
5.2.8 Ensure that allowedCapabilities is not present in PSPs for the cluster unless
|
||||
it is set to an empty array.
|
||||
|
||||
5.2.9 Review the use of capabilites in applications runnning on your cluster. Where a namespace
|
||||
contains applicaions which do not require any Linux capabities to operate consider adding
|
||||
a PSP which forbids the admission of containers which do not drop all capabilities.
|
||||
|
||||
5.3.1 If the CNI plugin in use does not support network policies, consideration should be given to
|
||||
making use of a different plugin, or finding an alternate mechanism for restricting traffic
|
||||
in the Kubernetes cluster.
|
||||
|
||||
5.3.2 Follow the documentation and create NetworkPolicy objects as you need them.
|
||||
|
||||
5.4.1 if possible, rewrite application code to read secrets from mounted secret files, rather than
|
||||
from environment variables.
|
||||
|
||||
5.4.2 Refer to the secrets management options offered by your cloud provider or a third-party
|
||||
secrets management solution.
|
||||
|
||||
5.5.1 Follow the Kubernetes documentation and setup image provenance.
|
||||
|
||||
5.6.1 Follow the documentation and create namespaces for objects in your deployment as you need
|
||||
them.
|
||||
|
||||
5.6.2 Seccomp is an alpha feature currently. By default, all alpha features are disabled. So, you
|
||||
would need to enable alpha features in the apiserver by passing "--feature-
|
||||
gates=AllAlpha=true" argument.
|
||||
Edit the /etc/kubernetes/apiserver file on the master node and set the KUBE_API_ARGS
|
||||
parameter to "--feature-gates=AllAlpha=true"
|
||||
KUBE_API_ARGS="--feature-gates=AllAlpha=true"
|
||||
Based on your system, restart the kube-apiserver service. For example:
|
||||
systemctl restart kube-apiserver.service
|
||||
Use annotations to enable the docker/default seccomp profile in your pod definitions. An
|
||||
example is as below:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: trustworthy-pod
|
||||
annotations:
|
||||
seccomp.security.alpha.kubernetes.io/pod: docker/default
|
||||
spec:
|
||||
containers:
|
||||
- name: trustworthy-container
|
||||
image: sotrustworthy:latest
|
||||
|
||||
5.6.3 Follow the Kubernetes documentation and apply security contexts to your pods. For a
|
||||
suggested list of security contexts, you may refer to the CIS Security Benchmark for Docker
|
||||
Containers.
|
||||
|
||||
5.6.4 Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
|
||||
resources and that all new resources are created in a specific namespace.
|
||||
|
||||
|
||||
== Summary ==
|
||||
0 checks PASS
|
||||
0 checks FAIL
|
||||
24 checks WARN
|
||||
0 checks INFO
|
||||
@@ -11,7 +11,7 @@ spec:
|
||||
- name: kube-bench
|
||||
# Push the image to your ECR and then refer to it here
|
||||
image: <ID.dkr.ecr.region.amazonaws.com/aquasec/kube-bench:ref>
|
||||
command: ["kube-bench", "--version", "1.11"]
|
||||
command: ["kube-bench", "node", "--benchmark", "eks-1.0"]
|
||||
volumeMounts:
|
||||
- name: var-lib-kubelet
|
||||
mountPath: /var/lib/kubelet
|
||||
|
||||
2
makefile
2
makefile
@@ -36,7 +36,7 @@ tests:
|
||||
GO111MODULE=on go test -v -short -race -timeout 30s -coverprofile=coverage.txt -covermode=atomic ./...
|
||||
|
||||
integration-tests: build-docker
|
||||
GO111MODULE=on go test ./integration/... -v -tags integration -timeout 600s -args -kubebenchImg=$(IMAGE_NAME)
|
||||
GO111MODULE=on go test ./integration/... -v -tags integration -timeout 1200s -args -kubebenchImg=$(IMAGE_NAME)
|
||||
|
||||
# creates a kind cluster to be used for development.
|
||||
HAS_KIND := $(shell command -v kind;)
|
||||
|
||||
Reference in New Issue
Block a user