---
controls:
version: "cis-1.8"
id: 1
text: "Control Plane Security Configuration"
type: "master"
groups:
  - id: 1.1
    text: "Control Plane Node Configuration Files"
    checks:
      - id: 1.1.1
        text: "Ensure that the API server pod specification file permissions are set to 600 or more restrictive (Automated)"
        audit: "/bin/sh -c 'if test -e $apiserverconf; then stat -c permissions=%a $apiserverconf; fi'"
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the
          control plane node.
          For example, chmod 600 $apiserverconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.2
        text: "Ensure that the API server pod specification file ownership is set to root:root (Automated)"
        audit: "/bin/sh -c 'if test -e $apiserverconf; then stat -c %U:%G $apiserverconf; fi'"
        tests:
          test_items:
            - flag: "root:root"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chown root:root $apiserverconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.3
        text: "Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive (Automated)"
        audit: "/bin/sh -c 'if test -e $controllermanagerconf; then stat -c permissions=%a $controllermanagerconf; fi'"
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chmod 600 $controllermanagerconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.4
        text: "Ensure that the controller manager pod specification file ownership is set to root:root (Automated)"
        audit: "/bin/sh -c 'if test -e $controllermanagerconf; then stat -c %U:%G $controllermanagerconf; fi'"
        tests:
          test_items:
            - flag: "root:root"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chown root:root $controllermanagerconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.5
        text: "Ensure that the scheduler pod specification file permissions are set to 600 or more restrictive (Automated)"
        audit: "/bin/sh -c 'if test -e $schedulerconf; then stat -c permissions=%a $schedulerconf; fi'"
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chmod 600 $schedulerconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.6
        text: "Ensure that the scheduler pod specification file ownership is set to root:root (Automated)"
        audit: "/bin/sh -c 'if test -e $schedulerconf; then stat -c %U:%G $schedulerconf; fi'"
        tests:
          test_items:
            - flag: "root:root"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chown root:root $schedulerconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.7
        text: "Ensure that the etcd pod specification file permissions are set to 600 or more restrictive (Automated)"

        audit: |
          /bin/sh -c 'if [ -e "$etcdconf" ]; then
            find "$etcdconf" -type f -name "*etcd*" \
              -exec stat -c "permissions=%a %n" {} +
          else
            echo "Directory not found"
          fi'
        use_multiple_values: true
        tests:
          bin_op: or
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
            - flag: "Directory not found"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chmod 600 $etcdconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.8
        text: "Ensure that the etcd pod specification file ownership is set to root:root (Automated)"
        audit: |
          /bin/sh -c 'if [ -e "$etcdconf" ]; then
            find "$etcdconf" -type f -name "*etcd*" -exec stat -c "%U:%G %n" {} +
          else
            echo "Directory not found"
          fi'
        use_multiple_values: true
        tests:
          bin_op: or
          test_items:
            - flag: "root:root"
            - flag: "Directory not found"
              set: true
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chown root:root $etcdconf
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for kube-apiserver.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.9
        text: "Ensure that the Container Network Interface file permissions are set to 600 or more restrictive (Manual)"
        audit: |
          ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty stat -c permissions=%a
          find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c permissions=%a
        use_multiple_values: true
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chmod 600 <path/to/cni/files>
        scored: false

      - id: 1.1.10
        text: "Ensure that the Container Network Interface file ownership is set to root:root (Manual)"
        audit: |
          ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty stat -c %U:%G
          find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c %U:%G
        use_multiple_values: true
        tests:
          test_items:
            - flag: "root:root"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chown root:root <path/to/cni/files>
        scored: false

      - id: 1.1.11
        text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Automated)"
        audit: |
          /bin/sh -c 'if [ -e "/node/var/lib/etcd" ]; then
            stat -c "%a" "/node/var/lib/etcd"
          else
            echo "Directory not found: /node/var/lib/etcd"
          fi'
        tests:
          bin_op: or
          test_items:
            - flag: "700"
              compare:
                op: eq
                value: "700"
              set: true
            - flag: "Directory not found: /node/var/lib/etcd"
        remediation: |
          On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
          from the command 'ps -ef | grep etcd'.
          Run the below command (based on the etcd data directory found above). For example,
          chmod 700 /var/lib/etcd
        scored: true

      - id: 1.1.12
        text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Automated)"
        audit: "stat -c %U:%G /node/var/lib/etcd"
        tests:
          test_items:
            - flag: "etcd:etcd"
              set: true
        remediation: |
          On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
          from the command 'ps -ef | grep etcd'.
          Run the below command (based on the etcd data directory found above).
          For example, chown etcd:etcd /var/lib/etcd
          Permissive - A system service account is required for etcd data directory ownership.
          Refer to Rancher's hardening guide for more details on how to configure this ownership.
        scored: true

      - id: 1.1.13
        text: "Ensure that the admin.conf file permissions are set to 600 or more restrictive (Automated)"
        audit: "/bin/sh -c 'if test -e /etc/kubernetes/admin.conf; then stat -c permissions=%a /etc/kubernetes/admin.conf; fi'"
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chmod 600 /etc/kubernetes/admin.conf
          Not Applicable -  Cluster provisioned by RKE does not store the kubernetes default kubeconfig credentials file on the nodes.
        scored: true

      - id: 1.1.14
        text: "Ensure that the admin.conf file ownership is set to root:root (Automated)"
        audit: "/bin/sh -c 'if test -e /etc/kubernetes/admin.conf; then stat -c %U:%G /etc/kubernetes/admin.conf; fi'"
        tests:
          test_items:
            - flag: "root:root"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example, chown root:root /etc/kubernetes/admin.conf
          Not Applicable -  Cluster provisioned by RKE does not store the kubernetes default kubeconfig credentials file on the nodes.
        scored: true

      - id: 1.1.15
        text: "Ensure that the scheduler.conf file permissions are set to 600 or more restrictive (Automated)"
        audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c permissions=%a $schedulerkubeconfig; fi'"
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chmod 600 $schedulerkubeconfig
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for scheduler.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.16
        text: "Ensure that the scheduler.conf file ownership is set to root:root (Automated)"
        audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c %U:%G $schedulerkubeconfig; fi'"
        tests:
          test_items:
            - flag: "root:root"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chown root:root $schedulerkubeconfig
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for scheduler.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.17
        text: "Ensure that the controller-manager.conf file permissions are set to 600 or more restrictive (Automated)"
        audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c permissions=%a $controllermanagerkubeconfig; fi'"
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chmod 600 $controllermanagerkubeconfig
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for controller-manager.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.18
        text: "Ensure that the controller-manager.conf file ownership is set to root:root (Automated)"
        audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c %U:%G $controllermanagerkubeconfig; fi'"
        tests:
          test_items:
            - flag: "root:root"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chown root:root $controllermanagerkubeconfig
          Not Applicable -  Cluster provisioned by RKE doesn't require or maintain a configuration file for controller-manager.
          All configuration is passed in as arguments at container run time.
        scored: true

      - id: 1.1.19
        text: "Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Automated)"
        audit: "check_files_owner_in_dir.sh /node/etc/kubernetes/ssl"
        tests:
          test_items:
            - flag: "true"
              compare:
                op: eq
                value: "true"
              set: true
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          chown -R root:root /etc/kubernetes/pki/
        scored: true

      - id: 1.1.20
        text: "Ensure that the Kubernetes PKI certificate file permissions are set to 600 or more restrictive (Manual)"
        audit: |
          if [ -d /node/etc/kubernetes/ssl ]; then
            find /node/etc/kubernetes/ssl -type f -name '*.pem' ! -name '*key.pem' \
              -exec stat -c 'permissions=%a %n' {} +
          else
            echo "Directory not found: /node/etc/kubernetes/ssl"
          fi
        use_multiple_values: true
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          find /node/etc/kubernetes/ssl/  -name '*.pem' ! -name '*key.pem' -exec chmod -R 600 {} +
        scored: false

      - id: 1.1.21
        text: "Ensure that the Kubernetes PKI key file permissions are set to 600 (Manual)"
        audit: |
          if [ -d /node/etc/kubernetes/ssl ]; then
            find /node/etc/kubernetes/ssl -type f -name '*key.pem' -exec stat -c 'permissions=%a %n' {} +
          else
            echo "Directory not found: /node/etc/kubernetes/ssl"
          fi
        use_multiple_values: true
        tests:
          test_items:
            - flag: "permissions"
              compare:
                op: bitmask
                value: "600"
        remediation: |
          Run the below command (based on the file location on your system) on the control plane node.
          For example,
          find /node/etc/kubernetes/ssl/ -name '*key.pem' -exec chmod -R 600 {} +
        scored: false

  - id: 1.2
    text: "API Server"
    checks:
      - id: 1.2.1
        text: "Ensure that the --anonymous-auth argument is set to false (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--anonymous-auth"
              compare:
                op: eq
                value: false
              set: true
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the below parameter.
          --anonymous-auth=false
        scored: true

      - id: 1.2.2
        text: "Ensure that the --token-auth-file parameter is not set (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--token-auth-file"
              set: false
        remediation: |
          Follow the documentation and configure alternate mechanisms for authentication. Then,
          edit the API server pod specification file $apiserverconf
          on the control plane node and remove the --token-auth-file=<filename> parameter.
        scored: true

      - id: 1.2.3
        text: "Ensure that the --DenyServiceExternalIPs is set (Manual)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--enable-admission-plugins"
              compare:
                op: has
                value: "DenyServiceExternalIPs"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and add the `DenyServiceExternalIPs` plugin
          to the enabled admission plugins, as such --enable-admission-plugin=DenyServiceExternalIPs.
        scored: false

      - id: 1.2.4
        text: "Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: and
          test_items:
            - flag: "--kubelet-client-certificate"
            - flag: "--kubelet-client-key"
        remediation: |
          Follow the Kubernetes documentation and set up the TLS connection between the
          apiserver and kubelets. Then, edit API server pod specification file
          $apiserverconf on the control plane node and set the
          kubelet client certificate and key parameters as below.
          --kubelet-client-certificate=<path/to/client-certificate-file>
          --kubelet-client-key=<path/to/client-key-file>
        scored: true

      - id: 1.2.5
        text: "Ensure that the --kubelet-certificate-authority argument is set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--kubelet-certificate-authority"
              set: true
        remediation: |
          Follow the Kubernetes documentation and setup the TLS connection between
          the apiserver and kubelets. Then, edit the API server pod specification file
          $apiserverconf on the control plane node and set the
          --kubelet-certificate-authority parameter to the path to the cert file for the certificate authority.
          --kubelet-certificate-authority=<ca-string>
          Permissive - When generating serving certificates, functionality could break in conjunction with hostname overrides which are required for certain cloud providers.
        scored: true

      - id: 1.2.6
        text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--authorization-mode"
              compare:
                op: nothave
                value: "AlwaysAllow"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --authorization-mode parameter to values other than AlwaysAllow.
          One such example could be as below.
          --authorization-mode=RBAC
        scored: true

      - id: 1.2.7
        text: "Ensure that the --authorization-mode argument includes Node (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--authorization-mode"
              compare:
                op: has
                value: "Node"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --authorization-mode parameter to a value that includes Node.
          --authorization-mode=Node,RBAC
        scored: true

      - id: 1.2.8
        text: "Ensure that the --authorization-mode argument includes RBAC (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--authorization-mode"
              compare:
                op: has
                value: "RBAC"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --authorization-mode parameter to a value that includes RBAC,
          for example `--authorization-mode=Node,RBAC`.
        scored: true

      - id: 1.2.9
        text: "Ensure that the admission control plugin EventRateLimit is set (Manual)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--enable-admission-plugins"
              compare:
                op: has
                value: "EventRateLimit"
        remediation: |
          Follow the Kubernetes documentation and set the desired limits in a configuration file.
          Then, edit the API server pod specification file $apiserverconf
          and set the below parameters.
          --enable-admission-plugins=...,EventRateLimit,...
          --admission-control-config-file=<path/to/configuration/file>
        scored: false

      - id: 1.2.10
        text: "Ensure that the admission control plugin AlwaysAdmit is not set (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--enable-admission-plugins"
              compare:
                op: nothave
                value: AlwaysAdmit
            - flag: "--enable-admission-plugins"
              set: false
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and either remove the --enable-admission-plugins parameter, or set it to a
          value that does not include AlwaysAdmit.
        scored: true

      - id: 1.2.11
        text: "Ensure that the admission control plugin AlwaysPullImages is set (Manual)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--enable-admission-plugins"
              compare:
                op: has
                value: "AlwaysPullImages"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --enable-admission-plugins parameter to include
          AlwaysPullImages.
          --enable-admission-plugins=...,AlwaysPullImages,...
        scored: false

      - id: 1.2.12
        text: "Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used (Manual)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--enable-admission-plugins"
              compare:
                op: has
                value: "SecurityContextDeny"
            - flag: "--enable-admission-plugins"
              compare:
                op: has
                value: "PodSecurityPolicy"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --enable-admission-plugins parameter to include
          SecurityContextDeny, unless PodSecurityPolicy is already in place.
          --enable-admission-plugins=...,SecurityContextDeny,...
          Permissive - Enabling Pod Security Policy can cause applications to unexpectedly fail.
        scored: false

      - id: 1.2.13
        text: "Ensure that the admission control plugin ServiceAccount is set (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--disable-admission-plugins"
              compare:
                op: nothave
                value: "ServiceAccount"
            - flag: "--disable-admission-plugins"
              set: false
        remediation: |
          Follow the documentation and create ServiceAccount objects as per your environment.
          Then, edit the API server pod specification file $apiserverconf
          on the control plane node and ensure that the --disable-admission-plugins parameter is set to a
          value that does not include ServiceAccount.
        scored: true

      - id: 1.2.14
        text: "Ensure that the admission control plugin NamespaceLifecycle is set (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--disable-admission-plugins"
              compare:
                op: nothave
                value: "NamespaceLifecycle"
            - flag: "--disable-admission-plugins"
              set: false
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --disable-admission-plugins parameter to
          ensure it does not include NamespaceLifecycle.
        scored: true

      - id: 1.2.15
        text: "Ensure that the admission control plugin NodeRestriction is set (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--enable-admission-plugins"
              compare:
                op: has
                value: "NodeRestriction"
        remediation: |
          Follow the Kubernetes documentation and configure NodeRestriction plug-in on kubelets.
          Then, edit the API server pod specification file $apiserverconf
          on the control plane node and set the --enable-admission-plugins parameter to a
          value that includes NodeRestriction.
          --enable-admission-plugins=...,NodeRestriction,...
        scored: true

      - id: 1.2.16
        text: "Ensure that the --profiling argument is set to false (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--profiling"
              compare:
                op: eq
                value: false
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the below parameter.
          --profiling=false
        scored: true

      - id: 1.2.17
        text: "Ensure that the --audit-log-path argument is set (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--audit-log-path"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --audit-log-path parameter to a suitable path and
          file where you would like audit logs to be written, for example,
          --audit-log-path=/var/log/apiserver/audit.log
        scored: true

      - id: 1.2.18
        text: "Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--audit-log-maxage"
              compare:
                op: gte
                value: 30
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --audit-log-maxage parameter to 30
          or as an appropriate number of days, for example,
          --audit-log-maxage=30
        scored: true

      - id: 1.2.19
        text: "Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--audit-log-maxbackup"
              compare:
                op: gte
                value: 10
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --audit-log-maxbackup parameter to 10 or to an appropriate
          value. For example,
          --audit-log-maxbackup=10
        scored: true

      - id: 1.2.20
        text: "Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--audit-log-maxsize"
              compare:
                op: gte
                value: 100
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --audit-log-maxsize parameter to an appropriate size in MB.
          For example, to set it as 100 MB, --audit-log-maxsize=100
        scored: true

      - id: 1.2.21
        text: "Ensure that the --request-timeout argument is set as appropriate (Manual)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        type: manual
        remediation: |
          Edit the API server pod specification file $apiserverconf
          and set the below parameter as appropriate and if needed.
          For example, --request-timeout=300s
        scored: false

      - id: 1.2.22
        text: "Ensure that the --service-account-lookup argument is set to true (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--service-account-lookup"
              set: false
            - flag: "--service-account-lookup"
              compare:
                op: eq
                value: true
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the below parameter.
          --service-account-lookup=true
          Alternatively, you can delete the --service-account-lookup parameter from this file so
          that the default takes effect.
        scored: true

      - id: 1.2.23
        text: "Ensure that the --service-account-key-file argument is set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--service-account-key-file"
        remediation: |
          Edit the API server pod specification file $apiserverconf
          on the control plane node and set the --service-account-key-file parameter
          to the public key file for service accounts. For example,
          --service-account-key-file=<filename>
        scored: true

      - id: 1.2.24
        text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: and
          test_items:
            - flag: "--etcd-certfile"
            - flag: "--etcd-keyfile"
        remediation: |
          Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd.
          Then, edit the API server pod specification file $apiserverconf
          on the control plane node and set the etcd certificate and key file parameters.
          --etcd-certfile=<path/to/client-certificate-file>
          --etcd-keyfile=<path/to/client-key-file>
        scored: true

      - id: 1.2.25
        text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          bin_op: and
          test_items:
            - flag: "--tls-cert-file"
            - flag: "--tls-private-key-file"
        remediation: |
          Follow the Kubernetes documentation and set up the TLS connection on the apiserver.
          Then, edit the API server pod specification file $apiserverconf
          on the control plane node and set the TLS certificate and private key file parameters.
          --tls-cert-file=<path/to/tls-certificate-file>
          --tls-private-key-file=<path/to/tls-key-file>
        scored: true

      - id: 1.2.26
        text: "Ensure that the --client-ca-file argument is set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--client-ca-file"
        remediation: |
          Follow the Kubernetes documentation and set up the TLS connection on the apiserver.
          Then, edit the API server pod specification file $apiserverconf
          on the control plane node and set the client certificate authority file.
          --client-ca-file=<path/to/client-ca-file>
        scored: true

      - id: 1.2.27
        text: "Ensure that the --etcd-cafile argument is set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--etcd-cafile"
        remediation: |
          Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd.
          Then, edit the API server pod specification file $apiserverconf
          on the control plane node and set the etcd certificate authority file parameter.
          --etcd-cafile=<path/to/ca-file>
        scored: true

      - id: 1.2.28
        text: "Ensure that the --encryption-provider-config argument is set as appropriate (Manual)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--encryption-provider-config"
        remediation: |
          Follow the Kubernetes documentation and configure a EncryptionConfig file.
          Then, edit the API server pod specification file $apiserverconf
          on the control plane node and set the --encryption-provider-config parameter to the path of that file.
          For example, --encryption-provider-config=</path/to/EncryptionConfig/File>
          Permissive - Enabling encryption changes how data can be recovered as data is encrypted.
        scored: false

      - id: 1.2.29
        text: "Ensure that encryption providers are appropriately configured (Manual)"
        audit: |
          ENCRYPTION_PROVIDER_CONFIG=$(ps -ef | grep $apiserverbin | grep -- --encryption-provider-config | sed 's%.*encryption-provider-config[= ]\([^ ]*\).*%\1%')
          if test -e $ENCRYPTION_PROVIDER_CONFIG; then grep -A1 'providers:' $ENCRYPTION_PROVIDER_CONFIG | tail -n1 | grep -o "[A-Za-z]*" | sed 's/^/provider=/'; fi
        tests:
          test_items:
            - flag: "provider"
              compare:
                op: valid_elements
                value: "aescbc,kms,secretbox"
        remediation: |
          Follow the Kubernetes documentation and configure a EncryptionConfig file.
          In this file, choose aescbc, kms or secretbox as the encryption provider.
          Permissive - Enabling encryption changes how data can be recovered as data is encrypted.
        scored: false

      - id: 1.2.30
        text: "Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Manual)"
        audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
        tests:
          test_items:
            - flag: "--tls-cipher-suites"
              compare:
                op: valid_elements
                value: "TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384"
        remediation: |
          Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
          on the control plane node and set the below parameter.
          --tls-cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,
          TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
          TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
          TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
          TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
          TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
          TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,
          TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384
        scored: false

  - id: 1.3
    text: "Controller Manager"
    checks:
      - id: 1.3.1
        text: "Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
        tests:
          test_items:
            - flag: "--terminated-pod-gc-threshold"
        remediation: |
          Edit the Controller Manager pod specification file $controllermanagerconf
          on the control plane node and set the --terminated-pod-gc-threshold to an appropriate threshold,
          for example, --terminated-pod-gc-threshold=10
        scored: true

      - id: 1.3.2
        text: "Ensure that the --profiling argument is set to false (Automated)"
        audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
        tests:
          test_items:
            - flag: "--profiling"
              compare:
                op: eq
                value: false
        remediation: |
          Edit the Controller Manager pod specification file $controllermanagerconf
          on the control plane node and set the below parameter.
          --profiling=false
        scored: true

      - id: 1.3.3
        text: "Ensure that the --use-service-account-credentials argument is set to true (Automated)"
        audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
        tests:
          test_items:
            - flag: "--use-service-account-credentials"
              compare:
                op: noteq
                value: false
        remediation: |
          Edit the Controller Manager pod specification file $controllermanagerconf
          on the control plane node to set the below parameter.
          --use-service-account-credentials=true
        scored: true

      - id: 1.3.4
        text: "Ensure that the --service-account-private-key-file argument is set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
        tests:
          test_items:
            - flag: "--service-account-private-key-file"
        remediation: |
          Edit the Controller Manager pod specification file $controllermanagerconf
          on the control plane node and set the --service-account-private-key-file parameter
          to the private key file for service accounts.
          --service-account-private-key-file=<filename>
        scored: true

      - id: 1.3.5
        text: "Ensure that the --root-ca-file argument is set as appropriate (Automated)"
        audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
        tests:
          test_items:
            - flag: "--root-ca-file"
        remediation: |
          Edit the Controller Manager pod specification file $controllermanagerconf
          on the control plane node and set the --root-ca-file parameter to the certificate bundle file`.
          --root-ca-file=<path/to/file>
        scored: true

      - id: 1.3.6
        text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Automated)"
        audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--feature-gates"
              compare:
                op: nothave
                value: "RotateKubeletServerCertificate=false"
              set: true
            - flag: "--feature-gates"
              set: false
        remediation: |
          Edit the Controller Manager pod specification file $controllermanagerconf
          on the control plane node and set the --feature-gates parameter to include RotateKubeletServerCertificate=true.
          --feature-gates=RotateKubeletServerCertificate=true
          Cluster provisioned by RKE handles certificate rotation directly through RKE.
        scored: true

      - id: 1.3.7
        text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)"
        audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--bind-address"
              compare:
                op: eq
                value: "127.0.0.1"
            - flag: "--bind-address"
              set: false
        remediation: |
          Edit the Controller Manager pod specification file $controllermanagerconf
          on the control plane node and ensure the correct value for the --bind-address parameter
        scored: true

  - id: 1.4
    text: "Scheduler"
    checks:
      - id: 1.4.1
        text: "Ensure that the --profiling argument is set to false (Automated)"
        audit: "/bin/ps -ef | grep $schedulerbin | grep -v grep"
        tests:
          test_items:
            - flag: "--profiling"
              compare:
                op: eq
                value: false
        remediation: |
          Edit the Scheduler pod specification file $schedulerconf file
          on the control plane node and set the below parameter.
          --profiling=false
        scored: true

      - id: 1.4.2
        text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)"
        audit: "/bin/ps -ef | grep $schedulerbin | grep -v grep"
        tests:
          bin_op: or
          test_items:
            - flag: "--bind-address"
              compare:
                op: eq
                value: "127.0.0.1"
            - flag: "--bind-address"
              set: false
        remediation: |
          Edit the Scheduler pod specification file $schedulerconf
          on the control plane node and ensure the correct value for the --bind-address parameter
        scored: true
