--- controls: version: "k3s-cis-1.7" id: 1 text: "Control Plane Security Configuration" type: "master" groups: - id: 1.1 text: "Control Plane Node Configuration Files" checks: - id: 1.1.1 text: "Ensure that the API server pod specification file permissions are set to 600 or more restrictive (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $apiserverconf; then stat -c permissions=%a $apiserverconf; fi'" tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 $apiserverconf Not Applicable. scored: true - id: 1.1.2 text: "Ensure that the API server pod specification file ownership is set to root:root (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $apiserverconf; then stat -c %U:%G $apiserverconf; fi'" tests: test_items: - flag: "root:root" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root $apiserverconf Not Applicable. scored: true - id: 1.1.3 text: "Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $controllermanagerconf; then stat -c permissions=%a $controllermanagerconf; fi'" tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 $controllermanagerconf Not Applicable. scored: true - id: 1.1.4 text: "Ensure that the controller manager pod specification file ownership is set to root:root (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $controllermanagerconf; then stat -c %U:%G $controllermanagerconf; fi'" tests: test_items: - flag: "root:root" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root $controllermanagerconf Not Applicable. scored: true - id: 1.1.5 text: "Ensure that the scheduler pod specification file permissions are set to 600 or more restrictive (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $schedulerconf; then stat -c permissions=%a $schedulerconf; fi'" tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 $schedulerconf Not Applicable. scored: true - id: 1.1.6 text: "Ensure that the scheduler pod specification file ownership is set to root:root (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $schedulerconf; then stat -c %U:%G $schedulerconf; fi'" tests: test_items: - flag: "root:root" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root $schedulerconf Not Applicable. scored: true - id: 1.1.7 text: "Ensure that the etcd pod specification file permissions are set to 600 or more restrictive (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $etcdconf; then find $etcdconf -name '*etcd*' | xargs stat -c permissions=%a; fi'" use_multiple_values: true tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 $etcdconf Not Applicable. scored: true - id: 1.1.8 text: "Ensure that the etcd pod specification file ownership is set to root:root (Automated)" type: "skip" audit: "/bin/sh -c 'if test -e $etcdconf; then find $etcdconf -name '*etcd*' | xargs stat -c %U:%G; fi'" use_multiple_values: true tests: test_items: - flag: "root:root" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root $etcdconf Not Applicable. scored: true - id: 1.1.9 text: "Ensure that the Container Network Interface file permissions are set to 600 or more restrictive (Automated)" type: "skip" audit: | ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty stat -c permissions=%a find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c permissions=%a use_multiple_values: true tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 Not Applicable. scored: false - id: 1.1.10 text: "Ensure that the Container Network Interface file ownership is set to root:root (Manual)" type: skip audit: | ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty stat -c %U:%G find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c %U:%G use_multiple_values: true tests: test_items: - flag: "root:root" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root Not Applicable. scored: false - id: 1.1.11 text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Automated)" audit: "stat -c %a $etcddatadir" tests: test_items: - flag: "700" compare: op: eq value: "700" set: true remediation: | On the etcd server node, get the etcd data directory, passed as an argument --data-dir, from the command '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 - id: 1.1.12 text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Automated)" audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %U:%G type: "skip" tests: test_items: - flag: "etcd:etcd" remediation: | On the etcd server node, get the etcd data directory, passed as an argument --data-dir, from the 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 Not Applicable. scored: true - id: 1.1.13 text: "Ensure that the admin.conf file permissions are set to 600 or more restrictive (Automated)" audit: "/bin/sh -c 'if test -e /var/lib/rancher/k3s/server/cred/admin.kubeconfig; then stat -c permissions=%a /var/lib/rancher/k3s/server/cred/admin.kubeconfig'" type: "skip" tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 /var/lib/rancher/k3s/server/cred/admin.kubeconfig scored: true - id: 1.1.14 text: "Ensure that the admin.conf file ownership is set to root:root (Automated)" audit: "/bin/sh -c 'if test -e /var/lib/rancher/k3s/server/cred/admin.kubeconfig; then stat -c %U:%G /var/lib/rancher/k3s/server/cred/admin.kubeconfig; fi'" tests: test_items: - flag: "root:root" compare: op: eq value: "root:root" set: true remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root /etc/kubernetes/admin.conf scored: true - id: 1.1.15 text: "Ensure that the scheduler.conf file permissions are set to 600 or more restrictive (Automated)" audit: "/bin/sh -c 'if test -e /var/lib/rancher/k3s/server/cred/scheduler.kubeconfig; then stat -c permissions=%a /var/lib/rancher/k3s/server/cred/scheduler.kubeconfig; fi'" tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 $schedulerkubeconfig scored: true - id: 1.1.16 text: "Ensure that the scheduler.conf file ownership is set to root:root (Automated)" audit: "/bin/sh -c 'if test -e /var/lib/rancher/k3s/server/cred/scheduler.kubeconfig; then stat -c %U:%G /var/lib/rancher/k3s/server/cred/scheduler.kubeconfig; fi'" tests: test_items: - flag: "root:root" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root $schedulerkubeconfig scored: true - id: 1.1.17 text: "Ensure that the controller-manager.conf file permissions are set to 600 or more restrictive (Automated)" audit: "/bin/sh -c 'if test -e /var/lib/rancher/k3s/server/cred/controller.kubeconfig; then stat -c permissions=%a /var/lib/rancher/k3s/server/cred/controller.kubeconfig; fi'" tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod 600 $controllermanagerkubeconfig scored: true - id: 1.1.18 text: "Ensure that the controller-manager.conf file ownership is set to root:root (Automated)" audit: "stat -c %U:%G /var/lib/rancher/k3s/server/cred/controller.kubeconfig" tests: test_items: - flag: "root:root" compare: op: eq value: "root:root" set: true remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown root:root $controllermanagerkubeconfig scored: true - id: 1.1.19 text: "Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Automated)" audit: "stat -c %U:%G /var/lib/rancher/k3s/server/tls" use_multiple_values: true tests: test_items: - flag: "root:root" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chown -R root:root /var/lib/rancher/k3s/server/tls scored: true - id: 1.1.20 text: "Ensure that the Kubernetes PKI certificate file permissions are set to 600 or more restrictive (Manual)" audit: "stat -c %n\ %a /var/lib/rancher/k3s/server/tls/*.crt" use_multiple_values: true tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod -R 600 /etc/kubernetes/pki/*.crt scored: false - id: 1.1.21 text: "Ensure that the Kubernetes PKI key file permissions are set to 600 (Manual)" audit: "stat -c %n\ %a /var/lib/rancher/k3s/server/tls/*.key" use_multiple_values: true tests: test_items: - flag: "permissions" compare: op: bitmask value: "600" remediation: | Run the below command (based on the file location on your system) on the control plane node. For example, chmod -R 600 /etc/kubernetes/pki/*.key scored: false - id: 1.2 text: "API Server" checks: - id: 1.2.1 text: "Ensure that the --anonymous-auth argument is set to false (Manual)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'anonymous-auth'" tests: test_items: - flag: "--anonymous-auth" compare: op: eq value: false remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the below parameter. --anonymous-auth=false scored: false - id: 1.2.2 text: "Ensure that the --token-auth-file parameter is not set (Automated)" audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep" tests: test_items: - flag: "--token-auth-file" set: false remediation: | Follow the documentation and configure alternate mechanisms for authentication. Then, edit the API server pod specification file $apiserverconf on the control plane node and remove the --token-auth-file= parameter. scored: true - id: 1.2.3 text: "Ensure that the --DenyServiceExternalIPs is not set (Automated)" audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep" tests: bin_op: or test_items: - flag: "--enable-admission-plugins" compare: op: nothave value: "DenyServiceExternalIPs" set: true - flag: "--enable-admission-plugins" set: false remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and remove the `DenyServiceExternalIPs` from enabled admission plugins. scored: true - id: 1.2.4 text: "Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'kubelet-certificate-authority'" tests: bin_op: and test_items: - flag: "--kubelet-client-certificate" - flag: "--kubelet-client-key" remediation: | Follow the Kubernetes documentation and set up the TLS connection between the apiserver and kubelets. Then, edit API server pod specification file $apiserverconf on the control plane node and set the kubelet client certificate and key parameters as below. --kubelet-client-certificate= --kubelet-client-key= scored: true - id: 1.2.5 text: "Ensure that the --kubelet-certificate-authority argument is set as appropriate (Automated)" type: "skip" audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep" tests: test_items: - flag: "--kubelet-certificate-authority" remediation: | Follow the Kubernetes documentation and setup the TLS connection between the apiserver and kubelets. Then, edit the API server pod specification file $apiserverconf on the control plane node and set the --kubelet-certificate-authority parameter to the path to the cert file for the certificate authority. --kubelet-certificate-authority= Permissive - When generating serving certificates, functionality could break in conjunction with hostname overrides which are required for certain cloud providers. scored: true - id: 1.2.6 text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'authorization-mode'" tests: test_items: - flag: "--authorization-mode" compare: op: nothave value: "AlwaysAllow" remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --authorization-mode parameter to values other than AlwaysAllow. One such example could be as below. --authorization-mode=RBAC scored: true - id: 1.2.7 text: "Ensure that the --authorization-mode argument includes Node (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'authorization-mode'" tests: test_items: - flag: "--authorization-mode" compare: op: has value: "Node" remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --authorization-mode parameter to a value that includes Node. --authorization-mode=Node,RBAC scored: true - id: 1.2.8 text: "Ensure that the --authorization-mode argument includes RBAC (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'authorization-mode'" tests: test_items: - flag: "--authorization-mode" compare: op: has value: "RBAC" remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --authorization-mode parameter to a value that includes RBAC, for example `--authorization-mode=Node,RBAC`. scored: true - id: 1.2.9 text: "Ensure that the admission control plugin EventRateLimit is set (Manual)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'enable-admission-plugins'" tests: test_items: - flag: "--enable-admission-plugins" compare: op: has value: "EventRateLimit" remediation: | Follow the Kubernetes documentation and set the desired limits in a configuration file. Then, edit the API server pod specification file $apiserverconf and set the below parameters. --enable-admission-plugins=...,EventRateLimit,... --admission-control-config-file= scored: false - id: 1.2.10 text: "Ensure that the admission control plugin AlwaysAdmit is not set (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'enable-admission-plugins'" tests: bin_op: or test_items: - flag: "--enable-admission-plugins" compare: op: nothave value: AlwaysAdmit - flag: "--enable-admission-plugins" set: false remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and either remove the --enable-admission-plugins parameter, or set it to a value that does not include AlwaysAdmit. scored: true - id: 1.2.11 text: "Ensure that the admission control plugin AlwaysPullImages is set (Manual)" audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep" tests: test_items: - flag: "--enable-admission-plugins" compare: op: has value: "AlwaysPullImages" remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --enable-admission-plugins parameter to include AlwaysPullImages. --enable-admission-plugins=...,AlwaysPullImages,... scored: false - id: 1.2.12 text: "Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used (Manual)" type: "skip" audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep" tests: bin_op: or test_items: - flag: "--enable-admission-plugins" compare: op: has value: "SecurityContextDeny" - flag: "--enable-admission-plugins" compare: op: has value: "PodSecurityPolicy" remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --enable-admission-plugins parameter to include SecurityContextDeny, unless PodSecurityPolicy is already in place. --enable-admission-plugins=...,SecurityContextDeny,... Permissive - Enabling Pod Security Policy can cause applications to unexpectedly fail. scored: false - id: 1.2.13 text: "Ensure that the admission control plugin ServiceAccount is set (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" tests: bin_op: or test_items: - flag: "--disable-admission-plugins" compare: op: nothave value: "ServiceAccount" - flag: "--disable-admission-plugins" set: false remediation: | Follow the documentation and create ServiceAccount objects as per your environment. Then, edit the API server pod specification file $apiserverconf on the control plane node and ensure that the --disable-admission-plugins parameter is set to a value that does not include ServiceAccount. scored: true - id: 1.2.14 text: "Ensure that the admission control plugin NamespaceLifecycle is set (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" tests: bin_op: or test_items: - flag: "--disable-admission-plugins" compare: op: nothave value: "NamespaceLifecycle" - flag: "--disable-admission-plugins" set: false remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --disable-admission-plugins parameter to ensure it does not include NamespaceLifecycle. scored: true - id: 1.2.15 text: "Ensure that the admission control plugin NodeRestriction is set (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'enable-admission-plugins'" tests: test_items: - flag: "--enable-admission-plugins" compare: op: has value: "NodeRestriction" remediation: | Follow the Kubernetes documentation and configure NodeRestriction plug-in on kubelets. Then, edit the API server pod specification file $apiserverconf on the control plane node and set the --enable-admission-plugins parameter to a value that includes NodeRestriction. --enable-admission-plugins=...,NodeRestriction,... scored: true - id: 1.2.16 text: "Ensure that the --secure-port argument is not set to 0 - NoteThis recommendation is obsolete and will be deleted per the consensus process (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'secure-port'" tests: bin_op: or test_items: - flag: "--secure-port" compare: op: gt value: 0 - flag: "--secure-port" set: false remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and either remove the --secure-port parameter or set it to a different (non-zero) desired port. scored: true - id: 1.2.17 text: "Ensure that the --profiling argument is set to false (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'profiling'" tests: test_items: - flag: "--profiling" compare: op: eq value: false remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the below parameter. --profiling=false scored: true - id: 1.2.18 text: "Ensure that the --audit-log-path argument is set (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" type: "skip" tests: test_items: - flag: "--audit-log-path" remediation: | Edit the API server pod specification file $apiserverconf on the control plane 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 Permissive. scored: true - id: 1.2.19 text: "Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" type: "skip" tests: test_items: - flag: "--audit-log-maxage" compare: op: gte value: 30 remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --audit-log-maxage parameter to 30 or as an appropriate number of days, for example, --audit-log-maxage=30 Permissive. scored: true - id: 1.2.20 text: "Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" type: "skip" tests: test_items: - flag: "--audit-log-maxbackup" compare: op: gte value: 10 remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --audit-log-maxbackup parameter to 10 or to an appropriate value. For example, --audit-log-maxbackup=10 Permissive. scored: true - id: 1.2.21 text: "Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" type: "skip" tests: test_items: - flag: "--audit-log-maxsize" compare: op: gte value: 100 remediation: | Edit the API server pod specification file $apiserverconf on the control plane 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 Permissive. scored: true - id: 1.2.22 text: "Ensure that the --request-timeout argument is set as appropriate (Manual)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" type: "skip" tests: test_items: - flag: "--request-timeout" remediation: | Edit the API server pod specification file $apiserverconf and set the below parameter as appropriate and if needed. For example, --request-timeout=300s Permissive. scored: false - id: 1.2.23 text: "Ensure that the --service-account-lookup argument is set to true (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" tests: bin_op: or test_items: - flag: "--service-account-lookup" set: false - flag: "--service-account-lookup" compare: op: eq value: true remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the below parameter. --service-account-lookup=true Alternatively, you can delete the --service-account-lookup parameter from this file so that the default takes effect. scored: true - id: 1.2.24 text: "Ensure that the --service-account-key-file argument is set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep -v grep" type: "skip" tests: test_items: - flag: "--service-account-key-file" remediation: | Edit the API server pod specification file $apiserverconf on the control plane node and set the --service-account-key-file parameter to the public key file for service accounts. For example, --service-account-key-file= scored: true - id: 1.2.25 text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1" tests: bin_op: and test_items: - flag: "--etcd-certfile" set: true - flag: "--etcd-keyfile" set: true remediation: | Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd. Then, edit the API server pod specification file $apiserverconf on the control plane node and set the etcd certificate and key file parameters. --etcd-certfile= --etcd-keyfile= scored: true - id: 1.2.26 text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep -A1 'Running kube-apiserver' | tail -n2" tests: bin_op: and test_items: - flag: "--tls-cert-file" set: true - flag: "--tls-private-key-file" set: true remediation: | Follow the Kubernetes documentation and set up the TLS connection on the apiserver. Then, edit the API server pod specification file $apiserverconf on the control plane node and set the TLS certificate and private key file parameters. --tls-cert-file= --tls-private-key-file= scored: true - id: 1.2.27 text: "Ensure that the --client-ca-file argument is set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'client-ca-file'" tests: test_items: - flag: "--client-ca-file" remediation: | Follow the Kubernetes documentation and set up the TLS connection on the apiserver. Then, edit the API server pod specification file $apiserverconf on the control plane node and set the client certificate authority file. --client-ca-file= scored: true - id: 1.2.28 text: "Ensure that the --etcd-cafile argument is set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'etcd-cafile'" tests: test_items: - flag: "--etcd-cafile" remediation: | Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd. Then, edit the API server pod specification file $apiserverconf on the control plane node and set the etcd certificate authority file parameter. --etcd-cafile= scored: true - id: 1.2.29 text: "Ensure that the --encryption-provider-config argument is set as appropriate (Manual)" type: "skip" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'encryption-provider-config'" tests: test_items: - flag: "--encryption-provider-config" remediation: | Follow the Kubernetes documentation and configure a EncryptionConfig file. Then, edit the API server pod specification file $apiserverconf on the control plane node and set the --encryption-provider-config parameter to the path of that file. For example, --encryption-provider-config= Permissive - Enabling encryption changes how data can be recovered as data is encrypted. scored: false - id: 1.2.30 text: "Ensure that encryption providers are appropriately configured (Manual)" type: "skip" audit: | ENCRYPTION_PROVIDER_CONFIG=$(ps -ef | grep $apiserverbin | grep -- --encryption-provider-config | sed 's%.*encryption-provider-config[= ]\([^ ]*\).*%\1%') if test -e $ENCRYPTION_PROVIDER_CONFIG; then grep -A1 'providers:' $ENCRYPTION_PROVIDER_CONFIG | tail -n1 | grep -o "[A-Za-z]*" | sed 's/^/provider=/'; fi tests: test_items: - flag: "provider" compare: op: valid_elements value: "aescbc,kms,secretbox" remediation: | Follow the Kubernetes documentation and configure a EncryptionConfig file. In this file, choose aescbc, kms or secretbox as the encryption provider. Permissive - Enabling encryption changes how data can be recovered as data is encrypted. scored: false - id: 1.2.32 text: "Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Manual)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-apiserver' | tail -n1 | grep 'tls-cipher-suites'" tests: test_items: - flag: "--tls-cipher-suites" compare: op: valid_elements value: "TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384" remediation: | Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml on the control plane node and set the below parameter. --tls-cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384 scored: false - id: 1.3 text: "Controller Manager" checks: - id: 1.3.1 text: "Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Manual)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-controller-manager' | tail -n1 | grep 'terminated-pod-gc-threshold'" tests: test_items: - flag: "--terminated-pod-gc-threshold" remediation: | Edit the Controller Manager pod specification file $controllermanagerconf on the control plane node and set the --terminated-pod-gc-threshold to an appropriate threshold, for example, --terminated-pod-gc-threshold=10 scored: false - id: 1.3.2 text: "Ensure that the --profiling argument is set to false (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-controller-manager' | tail -n1 | grep 'profiling'" tests: test_items: - flag: "--profiling" compare: op: eq value: false remediation: | Edit the Controller Manager pod specification file $controllermanagerconf on the control plane node and set the below parameter. --profiling=false scored: true - id: 1.3.3 text: "Ensure that the --use-service-account-credentials argument is set to true (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-controller-manager' | tail -n1 | grep 'use-service-account-credentials'" tests: test_items: - flag: "--use-service-account-credentials" compare: op: noteq value: false remediation: | Edit the Controller Manager pod specification file $controllermanagerconf on the control plane node to set the below parameter. --use-service-account-credentials=true scored: true - id: 1.3.4 text: "Ensure that the --service-account-private-key-file argument is set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-controller-manager' | tail -n1 | grep 'service-account-private-key-file'" tests: test_items: - flag: "--service-account-private-key-file" remediation: | Edit the Controller Manager pod specification file $controllermanagerconf on the control plane node and set the --service-account-private-key-file parameter to the private key file for service accounts. --service-account-private-key-file= scored: true - id: 1.3.5 text: "Ensure that the --root-ca-file argument is set as appropriate (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-controller-manager' | tail -n1 | grep 'root-ca-file'" tests: test_items: - flag: "--root-ca-file" remediation: | Edit the Controller Manager pod specification file $controllermanagerconf on the control plane node and set the --root-ca-file parameter to the certificate bundle file`. --root-ca-file= scored: true - id: 1.3.6 text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Automated)" type: "skip" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-controller-manager' | tail -n1 | grep 'RotateKubeletServerCertificate'" tests: bin_op: or test_items: - flag: "--feature-gates" compare: op: nothave value: "RotateKubeletServerCertificate=false" set: true - flag: "--feature-gates" set: false remediation: | Edit the Controller Manager pod specification file $controllermanagerconf on the control plane node and set the --feature-gates parameter to include RotateKubeletServerCertificate=true. --feature-gates=RotateKubeletServerCertificate=true Not Applicable. scored: true - id: 1.3.7 text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)" audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep" tests: bin_op: or test_items: - flag: "--bind-address" compare: op: eq value: "127.0.0.1" set: true - flag: "--bind-address" set: false remediation: | Edit the Controller Manager pod specification file $controllermanagerconf on the control plane node and ensure the correct value for the --bind-address parameter scored: true - id: 1.4 text: "Scheduler" checks: - id: 1.4.1 text: "Ensure that the --profiling argument is set to false (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-scheduler' | tail -n1" tests: test_items: - flag: "--profiling" compare: op: eq value: false set: true remediation: | Edit the Scheduler pod specification file $schedulerconf file on the control plane node and set the below parameter. --profiling=false scored: true - id: 1.4.2 text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)" audit: "journalctl -D /var/log/journal -u k3s | grep 'Running kube-scheduler' | tail -n1 | grep 'bind-address'" tests: bin_op: or test_items: - flag: "--bind-address" compare: op: eq value: "127.0.0.1" set: true - flag: "--bind-address" set: false remediation: | Edit the Scheduler pod specification file $schedulerconf on the control plane node and ensure the correct value for the --bind-address parameter scored: true