diff --git a/cfg/1.11-json/config.yaml b/cfg/1.11-json/config.yaml deleted file mode 100644 index 1091b13..0000000 --- a/cfg/1.11-json/config.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -# Config file for systems such as EKS where config is in JSON files -# Master nodes are controlled by EKS and not user-accessible -node: - kubernetes: - confs: - - "/var/lib/kubelet/kubeconfig" - kubeconfig: - - "/var/lib/kubelet/kubeconfig" - - kubelet: - defaultsvc: "/etc/systemd/system/kubelet.service" - defaultkubeconfig: "/var/lib/kubelet/kubeconfig" - - proxy: - defaultkubeconfig: "/var/lib/kubelet/kubeconfig" diff --git a/cfg/1.11-json/node.yaml b/cfg/1.11-json/node.yaml deleted file mode 100644 index 3d1e781..0000000 --- a/cfg/1.11-json/node.yaml +++ /dev/null @@ -1,523 +0,0 @@ ---- -controls: -version: 1.11 -id: 2 -text: "Worker Node Security Configuration" -type: "node" -groups: -- id: 2.1 - text: "Kubelet" - checks: - - id: 2.1.1 - text: "Ensure that the --allow-privileged argument is set to false (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: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--allow-privileged" - compare: - op: eq - value: false - set: true - remediation: | - Edit the kubelet service file $kubeletsvc - 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 - scored: true - - - id: 2.1.2 - text: "Ensure that the --anonymous-auth argument is set to false (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.authentication.anonymous.enabled}" - compare: - op: eq - value: false - set: true - 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: 2.1.3 - text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.authorization.mode}" - compare: - op: noteq - value: "AlwaysAllow" - set: true - 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: 2.1.4 - text: "Ensure that the --client-ca-file argument is set as appropriate (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - 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= - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.5 - text: "Ensure that the --read-only-port argument is set to 0 (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.readOnlyPort}" - compare: - op: eq - value: "0" - set: true - 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: 2.1.6 - text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: or - test_items: - - path: "{.streamingConnectionIdleTimeout}" - set: false - - path: "{.streamingConnectionIdleTimeout}" - compare: - op: noteq - value: 0 - set: true - 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: 2.1.7 - text: "Ensure that the --protect-kernel-defaults argument is set to true (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.protectKernelDefaults}" - compare: - op: eq - value: true - set: 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: 2.1.8 - text: "Ensure that the --make-iptables-util-chains argument is set to true (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: or - test_items: - - path: "{.makeIPTablesUtilChains}" - set: false - - path: "{.makeIPTablesUtilChains}" - compare: - op: eq - value: true - set: true - 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: 2.1.9 - text: "Ensure that the --hostname-override argument is not set (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.hostnameOverride}" - 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: 2.1.10 - text: "Ensure that the --event-qps argument is set to 0 (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.eventRecordQPS}" - compare: - op: eq - value: 0 - set: true - remediation: | - If using a Kubelet config file, edit the file to set eventRecordQPS: 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. - --event-qps=0 - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.11 - text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: and - test_items: - - path: "{.tlsCertFile}" - set: true - - path: "{.tlsPrivateKeyFile}" - set: true - remediation: | - 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 - $kubeletsvc on each worker node and - set the below parameters in KUBELET_CERTIFICATE_ARGS variable. - --tls-cert-file= - file= - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.12 - text: "Ensure that the --cadvisor-port argument is set to 0 (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: or - test_items: - - path: "{.cadvisorPort}" - compare: - op: eq - value: 0 - set: true - - path: "{.cadvisorPort}" - set: false - remediation: | - Edit the kubelet service file $kubeletsvc - on each worker node and set the below parameter in KUBELET_CADVISOR_ARGS variable. - --cadvisor-port=0 - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.13 - text: "Ensure that the --rotate-certificates argument is not set to false (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: or - test_items: - - path: "{.rotateCertificates}" - set: false - - path: "{.rotateCertificates}" - compare: - op: noteq - value: "false" - set: true - remediation: | - If using a Kubelet config file, edit the file to add the line rotateCertificates: true. - If using command line arguments, edit the kubelet service file $kubeletsvc - on each worker node and add --rotate-certificates=true argument to 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: 2.1.14 - text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.featureGates.RotateKubeletServerCertificate}" - compare: - op: eq - value: true - set: 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 - - - id: 2.1.15 - text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.tlsCipherSuites}" - compare: - op: valid_elements - value: "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" - set: true - remediation: | - 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 $kubeletsvc 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 - scored: false - -- id: 2.2 - text: "Configuration Files" - checks: - - id: 2.2.1 - text: "Ensure that the kubelet.conf file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $kubeletkubeconfig - scored: true - - - id: 2.2.2 - text: "Ensure that the kubelet.conf file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; 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 each worker - node. For example, - chown root:root $kubeletkubeconfig - scored: true - - - id: 2.2.3 - text: "Ensure that the kubelet service file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %a $kubeletsvc; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 755 $kubeletsvc - scored: true - - - id: 2.2.4 - text: "Ensure that the kubelet service file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'" - tests: - test_items: - - flag: "root:root" - set: true - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chown root:root $kubeletsvc - scored: true - - - id: 2.2.5 - 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: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $proxykubeconfig - - Note - This test reports "FAIL" if kube-proxy has been configured - using a kubernetes configMap. Only under this situation, the "FAIL" can safely be ignored - as the kube-proxy does not expose the kubeconfig file to the worker node. - scored: true - - - id: 2.2.6 - 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 the each worker - node. For example, - chown root:root $proxykubeconfig - - Note - This test reports "FAIL" if kube-proxy has been configured - using a kubernetes configMap. Only under this situation, the "FAIL" can safely be ignored - as the kube-proxy does not expose the kubeconfig file to the worker node. - scored: true - - - id: 2.2.7 - text: "Ensure that the certificate authorities file permissions are set to - 644 or more restrictive (Scored)" - type: "manual" - remediation: | - [Manual test] - Run the following command to modify the file permissions of the --client-ca-file - chmod 644 - scored: true - - - 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'" - tests: - test_items: - - flag: "root:root" - compare: - op: eq - value: root:root - set: true - remediation: | - Run the following command to modify the ownership of the --client-ca-file . - chown root:root - scored: true - - - id: 2.2.9 - 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: 2.2.10 - 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: - bin_op: or - 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 - remediation: | - Run the following command (using the config file location identied in the Audit step) - chmod 644 $kubeletconf - scored: true diff --git a/cfg/1.11/config.yaml b/cfg/1.11/config.yaml index b783945..4cbf4cf 100644 --- a/cfg/1.11/config.yaml +++ b/cfg/1.11/config.yaml @@ -1,2 +1,2 @@ --- -## Version-specific settings that override the values in cfg/config.yaml +## Version-specific settings that override the values in cfg/config.yaml \ No newline at end of file diff --git a/cfg/1.11/node.yaml b/cfg/1.11/node.yaml index 9ddbdaa..12b7e3b 100644 --- a/cfg/1.11/node.yaml +++ b/cfg/1.11/node.yaml @@ -1,23 +1,23 @@ --- controls: -version: 1.11 -id: 2 -text: "Worker Node Security Configuration" +version: "1.11" +id: "2" +text: Worker Node Security Configuration type: "node" groups: -- id: 2.1 - text: "Kubelet" +- id: "2.1" + text: Kubelet checks: - id: 2.1.1 - text: "Ensure that the --allow-privileged argument is set to false (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --allow-privileged argument is set to false (Scored) + audit: "ps -fC $kubeletbin " tests: test_items: - - flag: "--allow-privileged" + - flag: --allow-privileged + set: true compare: op: eq value: false - set: true remediation: | Edit the kubelet service file $kubeletsvc on each worker node and set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable. @@ -28,15 +28,17 @@ groups: scored: true - id: 2.1.2 - text: "Ensure that the --anonymous-auth argument is set to false (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --anonymous-auth argument is set to false (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--anonymous-auth" + - flag: --anonymous-auth + path: '{.authentication.anonymous.enabled}' + set: true compare: op: eq value: false - set: true remediation: | If using a Kubelet config file, edit the file to set authentication: anonymous: enabled to false . @@ -50,15 +52,17 @@ groups: scored: true - id: 2.1.3 - text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--authorization-mode" + - flag: --authorization-mode + path: '{.authorization.mode}' + set: true compare: op: nothave - value: "AlwaysAllow" - set: true + 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 @@ -71,11 +75,13 @@ groups: scored: true - id: 2.1.4 - text: "Ensure that the --client-ca-file argument is set as appropriate (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --client-ca-file argument is set as appropriate (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--client-ca-file" + - 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 @@ -90,15 +96,17 @@ groups: scored: true - id: 2.1.5 - text: "Ensure that the --read-only-port argument is set to 0 (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --read-only-port argument is set to 0 (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--read-only-port" + - flag: --read-only-port + path: '{.readOnlyPort}' + set: true compare: op: eq value: 0 - set: true 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 @@ -111,18 +119,21 @@ groups: scored: true - id: 2.1.6 - text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: - bin_op: or test_items: - - flag: "--streaming-connection-idle-timeout" + - flag: --streaming-connection-idle-timeout + path: '{.streamingConnectionIdleTimeout}' + set: true compare: op: noteq value: 0 - set: true - - flag: "--streaming-connection-idle-timeout" + - 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. @@ -136,15 +147,17 @@ groups: scored: true - id: 2.1.7 - text: "Ensure that the --protect-kernel-defaults argument is set to true (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --protect-kernel-defaults argument is set to true (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--protect-kernel-defaults" + - flag: --protect-kernel-defaults + path: '{.protectKernelDefaults}' + set: true compare: op: eq value: true - set: 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 @@ -157,18 +170,21 @@ groups: scored: true - id: 2.1.8 - text: "Ensure that the --make-iptables-util-chains argument is set to true (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --make-iptables-util-chains argument is set to true (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: - bin_op: or test_items: - - flag: "--make-iptables-util-chains" + - flag: --make-iptables-util-chains + path: '{.makeIPTablesUtilChains}' + set: true compare: op: eq value: true - set: true - - flag: "--make-iptables-util-chains" + - 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 @@ -181,11 +197,13 @@ groups: scored: true - id: 2.1.9 - text: "Ensure that the --hostname-override argument is not set (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --hostname-override argument is not set (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--hostname-override" + - flag: --hostname-override + path: '{.hostnameOverride}' set: false remediation: | Edit the kubelet service file $kubeletsvc @@ -197,15 +215,17 @@ groups: scored: true - id: 2.1.10 - text: "Ensure that the --event-qps argument is set to 0 (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --event-qps argument is set to 0 (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--event-qps" + - flag: --event-qps + path: '{.eventRecordQPS}' + set: true compare: op: eq value: 0 - set: true remediation: | If using a Kubelet config file, edit the file to set eventRecordQPS: 0 . If using command line arguments, edit the kubelet service file @@ -218,15 +238,18 @@ groups: scored: true - id: 2.1.11 - text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: - bin_op: and test_items: - - flag: "--tls-cert-file" + - flag: --tls-cert-file + path: '{.tlsCertFile}' set: true - - flag: "--tls-private-key-file" + - flag: --tls-private-key-file + path: '{.tlsPrivateKeyFile}' set: true + bin_op: and remediation: | 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 @@ -242,18 +265,21 @@ groups: scored: true - id: 2.1.12 - text: "Ensure that the --cadvisor-port argument is set to 0 (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --cadvisor-port argument is set to 0 (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: - bin_op: or test_items: - - flag: "--cadvisor-port" + - flag: --cadvisor-port + path: '{.cadvisorPort}' + set: true compare: op: eq value: 0 - set: true - - flag: "--cadvisor-port" + - flag: --cadvisor-port + path: '{.cadvisorPort}' set: false + bin_op: or remediation: | Edit the kubelet service file $kubeletsvc on each worker node and set the below parameter in KUBELET_CADVISOR_ARGS variable. @@ -264,21 +290,24 @@ groups: scored: true - id: 2.1.13 - text: "Ensure that the --rotate-certificates argument is not set to false (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the --rotate-certificates argument is not set to false (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: - bin_op: or test_items: - - flag: "--rotate-certificates" + - flag: --rotate-certificates + path: '{.rotateCertificates}' + set: true compare: op: eq value: true - set: true - - flag: "--rotate-certificates" + - 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. - If using command line arguments, edit the kubelet service file $kubeletsvc + If using command line arguments, edit the kubelet service file $kubeletsvc on each worker node and add --rotate-certificates=true argument to the KUBELET_CERTIFICATE_ARGS variable. Based on your system, restart the kubelet service. For example: systemctl daemon-reload @@ -286,15 +315,17 @@ groups: scored: true - id: 2.1.14 - text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the RotateKubeletServerCertificate argument is set to true (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "RotateKubeletServerCertificate" + - flag: RotateKubeletServerCertificate + path: '{.featureGates.RotateKubeletServerCertificate}' + set: true compare: op: eq value: true - set: true remediation: | Edit the kubelet service file $kubeletsvc on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable. @@ -305,208 +336,206 @@ groups: scored: true - id: 2.1.15 - text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)" - audit: "ps -fC $kubeletbin" + text: Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" tests: test_items: - - flag: "--tls-cipher-suites" + - flag: --tls-cipher-suites + path: '{.tlsCipherSuites}' + set: true compare: op: valid_elements - value: "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" - set: true + value: 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 remediation: | 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 $kubeletsvc 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 scored: false -- id: 2.2 - text: "Configuration Files" +- id: "2.2" + text: Configuration Files checks: - - id: 2.2.1 - text: "Ensure that the kubelet.conf file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $kubeletkubeconfig - scored: true - - - id: 2.2.2 - text: "Ensure that the kubelet.conf file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; 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 each worker - node. For example, - chown root:root $kubeletkubeconfig - scored: true + - id: 2.2.1 + text: Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored) + audit: '/bin/sh -c ''if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; 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" + bin_op: or + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chmod 644 $kubeletkubeconfig + scored: true - - id: 2.2.3 - text: "Ensure that the kubelet service file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %a $kubeletsvc; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 755 $kubeletsvc - scored: true + - id: 2.2.2 + text: Ensure that the kubelet.conf file ownership is set to root:root (Scored) + audit: '/bin/sh -c ''if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; fi'' ' + tests: + test_items: + - flag: root:root + set: true + compare: + op: eq + value: root:root + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chown root:root $kubeletkubeconfig + scored: true - - id: 2.2.4 - text: "Ensure that the kubelet service file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'" - tests: - test_items: - - flag: "root:root" - set: true - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chown root:root $kubeletsvc - scored: true + - id: 2.2.3 + text: Ensure that the kubelet service file permissions are set to 644 or more restrictive (Scored) + audit: '/bin/sh -c ''if test -e $kubeletsvc; then stat -c %a $kubeletsvc; 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" + bin_op: or + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chmod 755 $kubeletsvc + scored: true - - id: 2.2.5 - 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: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $proxykubeconfig - scored: true + - id: 2.2.4 + text: Ensure that the kubelet service file ownership is set to root:root (Scored) + audit: '/bin/sh -c ''if test -e $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'' ' + tests: + test_items: + - flag: root:root + set: true + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chown root:root $kubeletsvc + scored: true - - id: 2.2.6 - 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 the each worker - node. For example, - chown root:root $proxykubeconfig - scored: true + - id: 2.2.5 + 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" + 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" + bin_op: or + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chmod 644 $proxykubeconfig + scored: true - - id: 2.2.7 - text: "Ensure that the certificate authorities file permissions are set to - 644 or more restrictive (Scored)" - type: "manual" - remediation: | - [Manual test] - Run the following command to modify the file permissions of the --client-ca-file - chmod 644 - scored: true + - id: 2.2.6 + 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 the each worker + node. For example, + chown root:root $proxykubeconfig + scored: true - - 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'" - tests: - test_items: - - flag: "root:root" - compare: - op: eq - value: root:root - set: true - remediation: | - Run the following command to modify the ownership of the --client-ca-file . - chown root:root - scored: true + - id: 2.2.7 + text: Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Scored) + type: manual + remediation: | + Run the following command to modify the file permissions of the --client-ca-file + chmod 644 + scored: true - - id: 2.2.9 - 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: 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'' ' + tests: + test_items: + - flag: root:root + set: true + compare: + op: eq + value: root:root + remediation: | + Run the following command to modify the ownership of the --client-ca-file . + chown root:root + scored: true - - id: 2.2.10 - 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: - bin_op: or - 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 - remediation: | - Run the following command (using the config file location identied in the Audit step) - chmod 644 $kubeletconf - scored: true + - id: 2.2.9 + 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: 2.2.10 + 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" + bin_op: or + remediation: | + Run the following command (using the config file location identied in the Audit step) + chmod 644 $kubeletconf + scored: true diff --git a/cfg/1.13-json/config.yaml b/cfg/1.13-json/config.yaml deleted file mode 100644 index 1091b13..0000000 --- a/cfg/1.13-json/config.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -# Config file for systems such as EKS where config is in JSON files -# Master nodes are controlled by EKS and not user-accessible -node: - kubernetes: - confs: - - "/var/lib/kubelet/kubeconfig" - kubeconfig: - - "/var/lib/kubelet/kubeconfig" - - kubelet: - defaultsvc: "/etc/systemd/system/kubelet.service" - defaultkubeconfig: "/var/lib/kubelet/kubeconfig" - - proxy: - defaultkubeconfig: "/var/lib/kubelet/kubeconfig" diff --git a/cfg/1.13-json/node.yaml b/cfg/1.13-json/node.yaml deleted file mode 100644 index e3d4757..0000000 --- a/cfg/1.13-json/node.yaml +++ /dev/null @@ -1,505 +0,0 @@ ---- -controls: -version: 1.13 -id: 2 -text: "Worker Node Security Configuration" -type: "node" -groups: -- id: 2.1 - text: "Kubelet" - checks: - - id: 2.1.1 - text: "Ensure that the --anonymous-auth argument is set to false (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.authentication.anonymous.enabled}" - compare: - op: eq - value: false - set: true - 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: 2.1.2 - text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.authorization.mode}" - compare: - op: nothave - value: "AlwaysAllow" - set: true - 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: 2.1.3 - text: "Ensure that the --client-ca-file argument is set as appropriate (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - 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= - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.4 - text: "Ensure that the --read-only-port argument is set to 0 (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.readOnlyPort}" - compare: - op: eq - value: 0 - set: true - 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: 2.1.5 - text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: or - test_items: - - path: "{.streamingConnectionIdleTimeout}" - compare: - op: noteq - value: 0 - set: true - - path: "{.streamingConnectionIdleTimeout}" - set: false - 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: 2.1.6 - text: "Ensure that the --protect-kernel-defaults argument is set to true (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.protectKernelDefaults}" - compare: - op: eq - value: true - set: 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: 2.1.7 - text: "Ensure that the --make-iptables-util-chains argument is set to true (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: or - test_items: - - path: "{.makeIPTablesUtilChains}" - compare: - op: eq - value: true - set: true - - path: "{.makeIPTablesUtilChains}" - set: false - 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: 2.1.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: "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: 2.1.9 - text: "Ensure that the --event-qps argument is set to 0 (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.eventRecordQPS}" - compare: - op: eq - value: 0 - set: true - remediation: | - If using a Kubelet config file, edit the file to set eventRecordQPS: 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. - --event-qps=0 - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.10 - text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)" - audit: "cat $kubeletconf" - tests: - bin_op: and - test_items: - - path: "{.tlsCertFile}" - set: true - - path: "{.tlsPrivateKeyFile}" - set: true - remediation: | - 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 - $kubeletsvc on each worker node and - set the below parameters in KUBELET_CERTIFICATE_ARGS variable. - --tls-cert-file= - file= - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.11 - text: "[DEPRECATED] Ensure that the --cadvisor-port argument is set to 0" - # 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: "ps -fC $kubeletbin" - type: "skip" - tests: - bin_op: or - test_items: - - flag: "--cadvisor-port" - compare: - op: eq - value: 0 - set: true - - flag: "--cadvisor-port" - set: false - remediation: | - Edit the kubelet service file $kubeletsvc - on each worker node and set the below parameter in KUBELET_CADVISOR_ARGS variable. - --cadvisor-port=0 - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: false - - - id: 2.1.12 - text: "Ensure that the --rotate-certificates argument is not set to false (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.rotateCertificates}" - compare: - op: eq - value: true - set: true - remediation: | - If using a Kubelet config file, edit the file to add the line rotateCertificates: true. - If using command line arguments, edit the kubelet service file $kubeletsvc - on each worker node and add --rotate-certificates=true argument to 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: 2.1.13 - text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{.featureGates.RotateKubeletServerCertificate}" - compare: - op: eq - value: true - set: 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 - - - id: 2.1.14 - text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)" - audit: "cat $kubeletconf" - tests: - test_items: - - path: "{range .tlsCipherSuites[:]}{}{','}{end}" - compare: - op: valid_elements - value: "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" - set: true - remediation: | - 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 $kubeletsvc 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 - scored: false - -- id: 2.2 - text: "Configuration Files" - checks: - - id: 2.2.1 - text: "Ensure that the kubelet.conf file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $kubeletkubeconfig - scored: true - - - id: 2.2.2 - text: "Ensure that the kubelet.conf file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; 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 each worker - node. For example, - chown root:root $kubeletkubeconfig - scored: true - - - id: 2.2.3 - text: "Ensure that the kubelet service file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %a $kubeletsvc; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 755 $kubeletsvc - scored: true - - - id: 2.2.4 - text: "Ensure that the kubelet service file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'" - tests: - test_items: - - flag: "root:root" - set: true - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chown root:root $kubeletsvc - scored: true - - - id: 2.2.5 - 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: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $proxykubeconfig - - Note - This test reports "FAIL" if kube-proxy has been configured - using a kubernetes configMap. Only under this situation, the "FAIL" can safely be ignored - as the kube-proxy does not expose the kubeconfig file to the worker node. - scored: true - - - id: 2.2.6 - 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 the each worker - node. For example, - chown root:root $proxykubeconfig - - Note - This test reports "FAIL" if kube-proxy has been configured - using a kubernetes configMap. Only under this situation, the "FAIL" can safely be ignored - as the kube-proxy does not expose the kubeconfig file to the worker node. - scored: true - - - id: 2.2.7 - text: "Ensure that the certificate authorities file permissions are set to - 644 or more restrictive (Scored)" - type: "manual" - remediation: | - [Manual test] - Run the following command to modify the file permissions of the --client-ca-file - chmod 644 - scored: true - - - 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'" - tests: - test_items: - - flag: "root:root" - compare: - op: eq - value: root:root - set: true - remediation: | - Run the following command to modify the ownership of the --client-ca-file . - chown root:root - scored: true - - - id: 2.2.9 - 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: 2.2.10 - 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: - bin_op: or - 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 - remediation: | - Run the following command (using the config file location identied in the Audit step) - chmod 644 $kubeletconf - scored: true diff --git a/cfg/1.13/node.yaml b/cfg/1.13/node.yaml index 7939041..e0c7355 100644 --- a/cfg/1.13/node.yaml +++ b/cfg/1.13/node.yaml @@ -1,494 +1,525 @@ ---- -controls: -version: 1.13 -id: 2 -text: "Worker Node Security Configuration" -type: "node" -groups: -- id: 2.1 - text: "Kubelet" - checks: - - id: 2.1.1 - text: "Ensure that the --anonymous-auth argument is set to false (Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--anonymous-auth" - compare: - op: eq - value: false - set: true - 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: 2.1.2 - text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--authorization-mode" - compare: - op: nothave - value: "AlwaysAllow" - set: true - 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: 2.1.3 - text: "Ensure that the --client-ca-file argument is set as appropriate (Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--client-ca-file" - 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= - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.4 - text: "Ensure that the --read-only-port argument is set to 0 (Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--read-only-port" - compare: - op: eq - value: 0 - set: true - 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: 2.1.5 - text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored)" - audit: "ps -fC $kubeletbin" - tests: - bin_op: or - test_items: - - flag: "--streaming-connection-idle-timeout" - compare: - op: noteq - value: 0 - set: true - - flag: "--streaming-connection-idle-timeout" - set: false - 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: 2.1.6 - text: "Ensure that the --protect-kernel-defaults argument is set to true (Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--protect-kernel-defaults" - compare: - op: eq - value: true - set: 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: 2.1.7 - text: "Ensure that the --make-iptables-util-chains argument is set to true (Scored)" - audit: "ps -fC $kubeletbin" - tests: - bin_op: or - test_items: - - flag: "--make-iptables-util-chains" - compare: - op: eq - value: true - set: true - - flag: "--make-iptables-util-chains" - set: false - 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: 2.1.8 - text: "Ensure that the --hostname-override argument is not set (Scored)" - audit: "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: 2.1.9 - text: "Ensure that the --event-qps argument is set to 0 (Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--event-qps" - compare: - op: eq - value: 0 - set: true - remediation: | - If using a Kubelet config file, edit the file to set eventRecordQPS: 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. - --event-qps=0 - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.10 - text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored)" - audit: "ps -fC $kubeletbin" - tests: - bin_op: and - test_items: - - flag: "--tls-cert-file" - set: true - - flag: "--tls-private-key-file" - set: true - remediation: | - 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 - $kubeletsvc on each worker node and - set the below parameters in KUBELET_CERTIFICATE_ARGS variable. - --tls-cert-file= - file= - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: true - - - id: 2.1.11 - text: "[DEPRECATED] Ensure that the --cadvisor-port argument is set to 0 (Not Scored)" - audit: "ps -fC $kubeletbin" - type: "skip" - tests: - bin_op: or - test_items: - - flag: "--cadvisor-port" - compare: - op: eq - value: 0 - set: true - - flag: "--cadvisor-port" - set: false - remediation: | - Edit the kubelet service file $kubeletsvc - on each worker node and set the below parameter in KUBELET_CADVISOR_ARGS variable. - --cadvisor-port=0 - Based on your system, restart the kubelet service. For example: - systemctl daemon-reload - systemctl restart kubelet.service - scored: false - - - id: 2.1.12 - text: "Ensure that the --rotate-certificates argument is not set to false (Scored)" - audit: "ps -fC $kubeletbin" - tests: - bin_op: or - test_items: - - flag: "--rotate-certificates" - compare: - op: eq - value: true - set: true - - flag: "--rotate-certificates" - set: false - remediation: | - If using a Kubelet config file, edit the file to add the line rotateCertificates: true. - If using command line arguments, edit the kubelet service file $kubeletsvc - on each worker node and add --rotate-certificates=true argument to 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: 2.1.13 - text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "RotateKubeletServerCertificate" - compare: - op: eq - value: true - set: 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 - - - id: 2.1.14 - text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)" - audit: "ps -fC $kubeletbin" - tests: - test_items: - - flag: "--tls-cipher-suites" - compare: - op: valid_elements - value: "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" - set: true - remediation: | - 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 $kubeletsvc 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 - scored: false - -- id: 2.2 - text: "Configuration Files" - checks: - - id: 2.2.1 - text: "Ensure that the kubelet.conf file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $kubeletkubeconfig - scored: true - - - id: 2.2.2 - text: "Ensure that the kubelet.conf file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; 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 each worker - node. For example, - chown root:root $kubeletkubeconfig - scored: true - - - id: 2.2.3 - text: "Ensure that the kubelet service file permissions are set to 644 or - more restrictive (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %a $kubeletsvc; fi'" - tests: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 755 $kubeletsvc - scored: true - - - id: 2.2.4 - text: "Ensure that the kubelet service file ownership is set to root:root (Scored)" - audit: "/bin/sh -c 'if test -e $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'" - tests: - test_items: - - flag: "root:root" - set: true - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chown root:root $kubeletsvc - scored: true - - - id: 2.2.5 - 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: - bin_op: or - 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 - remediation: | - Run the below command (based on the file location on your system) on the each worker - node. For example, - chmod 644 $proxykubeconfig - scored: true - - - id: 2.2.6 - 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 the each worker - node. For example, - chown root:root $proxykubeconfig - scored: true - - - id: 2.2.7 - text: "Ensure that the certificate authorities file permissions are set to - 644 or more restrictive (Scored)" - type: "manual" - remediation: | - [Manual test] - Run the following command to modify the file permissions of the --client-ca-file - chmod 644 - scored: true - - - 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'" - tests: - test_items: - - flag: "root:root" - compare: - op: eq - value: root:root - set: true - remediation: | - Run the following command to modify the ownership of the --client-ca-file . - chown root:root - scored: true - - - id: 2.2.9 - 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: 2.2.10 - 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: - bin_op: or - 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 - remediation: | - Run the following command (using the config file location identied in the Audit step) - chmod 644 $kubeletconf - scored: true +--- +controls: +version: "1.13" +id: "2" +text: Worker Node Security Configuration +type: "node" +groups: +- id: "2.1" + text: Kubelet + checks: + - id: 2.1.1 + text: Ensure that the --anonymous-auth argument is set to false (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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: 2.1.2 + text: Ensure that the --authorization-mode argument is not set to AlwaysAllow (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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: 2.1.3 + text: Ensure that the --client-ca-file argument is set as appropriate (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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= + Based on your system, restart the kubelet service. For example: + systemctl daemon-reload + systemctl restart kubelet.service + scored: true + + - id: 2.1.4 + text: Ensure that the --read-only-port argument is set to 0 (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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: 2.1.5 + text: Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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: 2.1.6 + text: Ensure that the --protect-kernel-defaults argument is set to true (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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: 2.1.7 + text: Ensure that the --make-iptables-util-chains argument is set to true (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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: 2.1.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: "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: 2.1.9 + text: Ensure that the --event-qps argument is set to 0 (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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: 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. + --event-qps=0 + Based on your system, restart the kubelet service. For example: + systemctl daemon-reload + systemctl restart kubelet.service + scored: true + + - id: 2.1.10 + text: Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" + tests: + test_items: + - flag: --tls-cert-file + path: '{.tlsCertFile}' + set: true + - flag: --tls-private-key-file + path: '{.tlsPrivateKeyFile}' + set: true + bin_op: and + remediation: | + 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 + $kubeletsvc on each worker node and + set the below parameters in KUBELET_CERTIFICATE_ARGS variable. + --tls-cert-file= + file= + Based on your system, restart the kubelet service. For example: + systemctl daemon-reload + systemctl restart kubelet.service + scored: true + + - id: 2.1.11 + text: '[DEPRECATED] Ensure that the --cadvisor-port argument is set to 0' + # 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: "ps -fC $kubeletbin " + type: skip + tests: + test_items: + - flag: --cadvisor-port + set: true + compare: + op: eq + value: 0 + - flag: --cadvisor-port + set: false + bin_op: or + remediation: | + Edit the kubelet service file $kubeletsvc + on each worker node and set the below parameter in KUBELET_CADVISOR_ARGS variable. + --cadvisor-port=0 + Based on your system, restart the kubelet service. For example: + systemctl daemon-reload + systemctl restart kubelet.service + scored: false + + - id: 2.1.12 + text: Ensure that the --rotate-certificates argument is not set to false (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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. + If using command line arguments, edit the kubelet service file $kubeletsvc + on each worker node and add --rotate-certificates=true argument to 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: 2.1.13 + text: Ensure that the RotateKubeletServerCertificate argument is set to true (Scored) + audit: "ps -fC $kubeletbin" + audit_config: "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 + + - id: 2.1.14 + text: Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored) + audit: "ps -fC $kubeletbin" + audit_config: "cat $kubeletconf" + tests: + test_items: + - flag: --tls-cipher-suites + path: '{range .tlsCipherSuites[:]}{}{'',''}{end}' + set: true + compare: + op: valid_elements + value: 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 + remediation: | + 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 $kubeletsvc 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 + scored: false + +- id: "2.2" + text: Configuration Files + checks: + - id: 2.2.1 + text: Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Scored) + audit: '/bin/sh -c ''if test -e $kubeletkubeconfig; then stat -c %a $kubeletkubeconfig; 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" + bin_op: or + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chmod 644 $kubeletkubeconfig + scored: true + + - id: 2.2.2 + text: Ensure that the kubelet.conf file ownership is set to root:root (Scored) + audit: '/bin/sh -c ''if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; fi'' ' + tests: + test_items: + - flag: root:root + set: true + compare: + op: eq + value: root:root + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chown root:root $kubeletkubeconfig + scored: true + + - id: 2.2.3 + text: Ensure that the kubelet service file permissions are set to 644 or more restrictive (Scored) + audit: '/bin/sh -c ''if test -e $kubeletsvc; then stat -c %a $kubeletsvc; 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" + bin_op: or + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chmod 755 $kubeletsvc + scored: true + + - id: 2.2.4 + text: Ensure that the kubelet service file ownership is set to root:root (Scored) + audit: '/bin/sh -c ''if test -e $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'' ' + tests: + test_items: + - flag: root:root + set: true + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chown root:root $kubeletsvc + scored: true + + - id: 2.2.5 + 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" + 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" + bin_op: or + remediation: | + Run the below command (based on the file location on your system) on the each worker + node. For example, + chmod 644 $proxykubeconfig + scored: true + + - id: 2.2.6 + 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 the each worker + node. For example, + chown root:root $proxykubeconfig + scored: true + + - id: 2.2.7 + text: Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Scored) + type: manual + tests: {} + remediation: | + Run the following command to modify the file permissions of the --client-ca-file + chmod 644 + scored: true + + - 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'' ' + tests: + test_items: + - flag: root:root + set: true + compare: + op: eq + value: root:root + remediation: | + Run the following command to modify the ownership of the --client-ca-file . + chown root:root + scored: true + + - id: 2.2.9 + 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: 2.2.10 + 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" + bin_op: or + remediation: | + Run the following command (using the config file location identied in the Audit step) + chmod 644 $kubeletconf + scored: true diff --git a/cfg/config.yaml b/cfg/config.yaml index aff949a..0ccfdf8 100644 --- a/cfg/config.yaml +++ b/cfg/config.yaml @@ -102,6 +102,7 @@ node: - "/etc/kubernetes/kubelet/kubelet-config.json" - "/home/kubernetes/kubelet-config.yaml" - "/etc/default/kubelet" + - "/var/lib/kubelet/kubeconfig" ## Due to the fact that the kubelet might be configured ## without a kubelet-config file, we use a work-around ## of pointing to the systemd service file (which can also diff --git a/check/check.go b/check/check.go index d3b3fb2..d7c4d8a 100644 --- a/check/check.go +++ b/check/check.go @@ -46,14 +46,12 @@ const ( MASTER NodeType = "master" // NODE a node NODE NodeType = "node" -) + // FEDERATED a federated deployment. + FEDERATED NodeType = "federated" -func handleError(err error, context string) (errmsg string) { - if err != nil { - errmsg = fmt.Sprintf("%s, error: %s\n", context, err) - } - return -} + // MANUAL Check Type + MANUAL string = "manual" +) // Check contains information about a recommendation in the // CIS Kubernetes 1.6+ document. @@ -61,8 +59,10 @@ 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"` @@ -94,6 +94,14 @@ func (r *defaultRunner) Run(c *Check) State { // the results. func (c *Check) run() State { + // Since this is an Scored check + // without tests return a 'WARN' to alert + // the user that this check needs attention + if c.Scored && len(strings.TrimSpace(c.Type)) == 0 && c.Tests == nil { + c.State = WARN + return c.State + } + // If check type is skip, force result to INFO if c.Type == "skip" { c.State = INFO @@ -101,109 +109,72 @@ func (c *Check) run() State { } // If check type is manual force result to WARN - if c.Type == "manual" { + if c.Type == MANUAL { c.State = WARN return c.State } - var out bytes.Buffer - var errmsgs string - - // Check if command exists or exit with WARN. - for _, cmd := range c.Commands { - if !isShellCommand(cmd.Path) { - c.State = WARN - return c.State - } - } + lastCommand := c.Audit + hasAuditConfig := c.ConfigCommands != nil - // Run commands. - n := len(c.Commands) - if n == 0 { - // Likely a warning message. - c.State = WARN + state, finalOutput, retErrmsgs := performTest(c.Audit, c.Commands, c.Tests) + if len(state) > 0 { + c.State = state return c.State } + errmsgs := retErrmsgs + + // If something went wrong with the 'Audit' command + // and an 'AuditConfig' command was provided, use it to + // execute tests + if (finalOutput == nil || !finalOutput.testResult) && hasAuditConfig { + lastCommand = c.AuditConfig + + nItems := len(c.Tests.TestItems) + // The reason we're creating a copy of the "tests" + // is so that tests can executed + // with the AuditConfig command + // against the Path only + currentTests := &tests{ + BinOp: c.Tests.BinOp, + TestItems: make([]*testItem, nItems), + } - // Each command runs, - // cmd0 out -> cmd1 in, cmd1 out -> cmd2 in ... cmdn out -> os.stdout - // cmd0 err should terminate chain - cs := c.Commands - - // Initialize command pipeline - cs[n-1].Stdout = &out - i := 1 - - var err error - errmsgs = "" - - for i < n { - cs[i-1].Stdout, err = cs[i].StdinPipe() - errmsgs += handleError( - err, - fmt.Sprintf("failed to run: %s\nfailed command: %s", - c.Audit, - cs[i].Args, - ), - ) - i++ - } - - // Start command pipeline - i = 0 - for i < n { - err := cs[i].Start() - errmsgs += handleError( - err, - fmt.Sprintf("failed to run: %s\nfailed command: %s", - c.Audit, - cs[i].Args, - ), - ) - i++ - } - - // Complete command pipeline - i = 0 - for i < n { - err := cs[i].Wait() - errmsgs += handleError( - err, - fmt.Sprintf("failed to run: %s\nfailed command:%s", - c.Audit, - cs[i].Args, - ), - ) - - if i < n-1 { - cs[i].Stdout.(io.Closer).Close() + for i := 0; i < nItems; i++ { + ti := c.Tests.TestItems[i] + nti := &testItem{ + // Path is used to test Command Param values + // AuditConfig ==> Path + Path: ti.Path, + Set: ti.Set, + Compare: ti.Compare, + } + currentTests.TestItems[i] = nti } - i++ + state, finalOutput, retErrmsgs = performTest(c.AuditConfig, c.ConfigCommands, currentTests) + if len(state) > 0 { + c.State = state + return c.State + } + errmsgs += retErrmsgs } - glog.V(3).Info(out.String()) - - finalOutput := c.Tests.execute(out.String()) - if finalOutput != nil { + if finalOutput != nil && finalOutput.testResult { + c.State = PASS c.ActualValue = finalOutput.actualResult c.ExpectedResult = finalOutput.ExpectedResult - if finalOutput.testResult { - c.State = PASS + glog.V(3).Infof("Check.ID: %s Command: %q TestResult: %t Score: %q \n", c.ID, lastCommand, finalOutput.testResult, c.State) + } else { + if c.Scored { + c.State = FAIL } else { - if c.Scored { - c.State = FAIL - } else { - c.State = WARN - } + c.State = WARN } - } else { - errmsgs += handleError( - fmt.Errorf("final output is nil"), - fmt.Sprintf("failed to run: %s\n", - c.Audit, - ), - ) + } + + if finalOutput == nil { + glog.V(3).Infof("Check.ID: %s Command: %q TestResult: <> \n", c.ID, lastCommand) } if errmsgs != "" { @@ -216,6 +187,7 @@ func (c *Check) run() State { // 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, "|") @@ -272,3 +244,86 @@ func isShellCommand(s string) bool { } return false } + +func performTest(audit string, commands []*exec.Cmd, tests *tests) (State, *testOutput, string) { + if len(strings.TrimSpace(audit)) == 0 { + return "", failTestItem("missing command"), "" + } + + var out bytes.Buffer + state, retErrmsgs := runExecCommands(audit, commands, &out) + if len(state) > 0 { + return state, nil, "" + } + errmsgs := retErrmsgs + + finalOutput := tests.execute(out.String()) + if finalOutput == nil { + errmsgs += fmt.Sprintf("Final output is <>. Failed to run: %s\n", audit) + } + + return "", finalOutput, errmsgs +} + +func runExecCommands(audit string, commands []*exec.Cmd, out *bytes.Buffer) (State, string) { + var err error + errmsgs := "" + + // Check if command exists or exit with WARN. + for _, cmd := range commands { + if !isShellCommand(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++ + } + + glog.V(3).Infof("Command %q - Output:\n\n %s\n", audit, out.String()) + return "", errmsgs +} diff --git a/check/check_test.go b/check/check_test.go index 2cf6e3c..e946428 100644 --- a/check/check_test.go +++ b/check/check_test.go @@ -25,14 +25,13 @@ func TestCheck_Run(t *testing.T) { } testCases := []TestCase{ - {check: Check{Type: "manual"}, Expected: WARN}, + {check: Check{Type: MANUAL}, Expected: WARN}, {check: Check{Type: "skip"}, Expected: INFO}, {check: Check{Type: "", Scored: false}, Expected: WARN}, // Not scored checks with no type should be marked warn {check: Check{Type: "", Scored: true}, Expected: WARN}, // If there are no tests in the check, warn - {check: Check{Type: "manual", Scored: false}, Expected: WARN}, + {check: Check{Type: MANUAL, Scored: false}, Expected: WARN}, {check: Check{Type: "skip", Scored: false}, Expected: INFO}, } - for _, testCase := range testCases { testCase.check.run() @@ -42,3 +41,55 @@ func TestCheck_Run(t *testing.T) { } } } + +func TestCheckAuditConfig(t *testing.T) { + + cases := []struct { + *Check + expected State + }{ + { + controls.Groups[1].Checks[0], + "PASS", + }, + { + controls.Groups[1].Checks[1], + "FAIL", + }, + { + controls.Groups[1].Checks[2], + "FAIL", + }, + { + controls.Groups[1].Checks[3], + "PASS", + }, + { + controls.Groups[1].Checks[4], + "FAIL", + }, + { + controls.Groups[1].Checks[5], + "PASS", + }, + { + controls.Groups[1].Checks[6], + "FAIL", + }, + { + controls.Groups[1].Checks[7], + "PASS", + }, + { + controls.Groups[1].Checks[8], + "FAIL", + }, + } + + for _, c := range cases { + c.run() + if c.State != c.expected { + t.Errorf("%s, expected:%v, got:%v\n", c.Text, c.expected, c.State) + } + } +} diff --git a/check/controls.go b/check/controls.go index 0a6183c..86828de 100644 --- a/check/controls.go +++ b/check/controls.go @@ -17,6 +17,7 @@ package check import ( "encoding/json" "fmt" + "github.com/golang/glog" "gopkg.in/yaml.v2" ) @@ -69,7 +70,12 @@ func NewControls(t NodeType, in []byte) (*Controls, error) { // 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) + } } } diff --git a/check/data b/check/data index 7e41a9f..8711773 100644 --- a/check/data +++ b/check/data @@ -307,3 +307,116 @@ groups: op: regex value: '^1\.12.*$' set: true + +- id: 2.1 + text: "audit and audit_config commands" + checks: + - id: 0 + text: "audit finds flag and passes, audit_config doesn't exist -> pass" + audit: "echo flag=correct" + tests: + test_items: + - flag: "flag" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 1 + text: "audit finds flag and fails, audit_config doesn't exist -> fail" + audit: "echo flag=wrong" + tests: + test_items: + - flag: "flag" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 2 + text: "audit doesn't find flag, audit_config doesn't exist -> fail" + audit: "echo somethingElse=correct" + tests: + test_items: + - flag: "flag" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 3 + text: "audit doesn't find flag, audit_config has correct setting -> pass" + audit: "echo somethingElse=correct" + audit_config: "echo 'flag: correct'" + tests: + test_items: + - flag: "flag" + path: "{.flag}" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 4 + text: "audit doesn't find flag, audit_config has wrong setting -> fail" + audit: "echo somethingElse=correct" + audit_config: "echo 'flag: wrong'" + tests: + test_items: + - flag: "flag" + path: "{.flag}" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 5 + text: "audit finds correct flag, audit_config has wrong setting -> pass" + audit: "echo flag=correct" + audit_config: "echo 'flag: wrong'" + tests: + test_items: + - flag: "flag" + path: "{.flag}" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 6 + text: "neither audit nor audit_config has correct setting -> fail" + audit: "echo flag=wrong" + audit_config: "echo 'flag: wrong'" + tests: + test_items: + - flag: "flag" + path: "{.flag}" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 7 + text: "audit isn't present, superfluous flag field,audit_config is correct -> pass" + audit_config: "echo 'flag: correct'" + tests: + test_items: + - flag: "flag" + path: "{.flag}" + compare: + op: eq + value: "correct" + set: true + scored: true + - id: 8 + text: "audit isn't present, superfluous flag field,audit_config is wrong -> fail" + audit_config: "echo 'flag: wrong'" + tests: + test_items: + - flag: "flag" + path: "{.flag}" + compare: + op: eq + value: "correct" + set: true + scored: true diff --git a/cmd/common.go b/cmd/common.go index aee3cbf..fda84f7 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -216,6 +216,7 @@ func loadConfig(nodetype check.NodeType) string { exitWithError(fmt.Errorf("Version check failed: %s\nAlternatively, you can specify the version with --version", err)) } } + path, err := getConfigFilePath(kubeVersion, runningVersion, file) if err != nil { exitWithError(fmt.Errorf("can't find %s controls file in %s: %v", nodetype, cfgDir, err))