> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ensure Root CA File Argument Is Appropriate

### More Info:

Allow pods to verify the API servers serving certificate before establishing connections.

### Risk Level

Low

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On every control plane node, back up the existing manifest:
           ```bash theme={null}
           sudo cp -a /etc/kubernetes/manifests/kube-controller-manager.yaml /etc/kubernetes/manifests/kube-controller-manager.yaml.bak
           ```

        2. On the same node, identify the appropriate root CA bundle file present on the host (coordinate with your PKI/security team if unsure). Common examples include:
           ```bash theme={null}
           ls -l /etc/kubernetes/pki/ca.crt
           ls -l /etc/ssl/certs/ca-bundle.crt
           ls -l /etc/ssl/certs/ca-certificates.crt
           ```

        3. Edit the controller manager manifest on the control plane node to configure the root CA file (replace the example path with the correct bundle you identified in step 2):
           ```bash theme={null}
           sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml
           ```
           Under the `command:` or `args:` list for `kube-controller-manager`, add (or update) the flag, for example:
           ```yaml theme={null}
           - --root-ca-file=/etc/kubernetes/pki/ca.crt
           ```
           Save and exit. Because this is a static pod manifest, the kube-controller-manager pod will be automatically restarted by the kubelet when the file changes.

        4. (If needed) Ensure the configured file is readable by the kube-controller-manager container on the control plane node:
           ```bash theme={null}
           sudo ls -l /etc/kubernetes/pki/ca.crt
           ```
           If the file is not already accessible in the pod via a volume mount, add an appropriate `hostPath` volume and `volumeMount` in `kube-controller-manager.yaml` pointing to the directory that contains the CA file, then save the manifest again to trigger a restart.

        5. Wait for the kube-controller-manager pod to restart and become Running on the control plane node:
           ```bash theme={null}
           sudo crictl pods | grep kube-controller-manager || sudo docker ps | grep kube-controller-manager
           ```

        6. Verification on every control plane node (derived from the audit command): confirm the running process includes the `--root-ca-file` flag with the correct path:
           ```bash theme={null}
           /bin/ps -ef | grep kube-controller-manager | grep -v grep
           ```
           Check that the output shows `--root-ca-file=/etc/kubernetes/pki/ca.crt` (or the exact path you configured).
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the kube-controller-manager static pod manifest or its process flags, so this finding cannot be fixed via the Kubernetes API. To remediate, you must edit `/etc/kubernetes/manifests/kube-controller-manager.yaml` directly on every control plane node as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Automation: Ensure kube-controller-manager has --root-ca-file set
        # Scope: Run on every control plane node (with root privileges)
        #
        # This script:
        #   - Backs up /etc/kubernetes/manifests/kube-controller-manager.yaml
        #   - Ensures --root-ca-file=/etc/kubernetes/pki/ca.crt is present
        #   - Is idempotent and safe to re-run
        #   - Verifies the running process flags
        #
        # NOTE:
        #   - Editing a static pod manifest under /etc/kubernetes/manifests will
        #     cause the kube-controller-manager pod to be restarted by the kubelet.

        set -euo pipefail

        MANIFEST="/etc/kubernetes/manifests/kube-controller-manager.yaml"
        BACKUP_DIR="/etc/kubernetes/manifests/backup-$(date +%Y%m%d)"
        ROOT_CA_PATH="/etc/kubernetes/pki/ca.crt"
        FLAG_NAME="--root-ca-file"
        FLAG_VALUE="${FLAG_NAME}=${ROOT_CA_PATH}"

        require_root() {
          if [ "$(id -u)" -ne 0 ]; then
            echo "ERROR: This script must be run as root on each control plane node." >&2
            exit 1
          fi
        }

        check_files() {
          if [ ! -f "${MANIFEST}" ]; then
            echo "ERROR: Manifest not found: ${MANIFEST}" >&2
            exit 1
          fi
          if [ ! -f "${ROOT_CA_PATH}" ]; then
            echo "ERROR: Root CA file not found: ${ROOT_CA_PATH}" >&2
            echo "       Adjust ROOT_CA_PATH in this script if your CA bundle is elsewhere." >&2
            exit 1
          fi
        }

        backup_manifest() {
          mkdir -p "${BACKUP_DIR}"
          local base
          base="$(basename "${MANIFEST}")"
          if [ ! -f "${BACKUP_DIR}/${base}" ]; then
            cp -p "${MANIFEST}" "${BACKUP_DIR}/${base}"
            echo "Backup created at ${BACKUP_DIR}/${base}"
          else
            echo "Backup already exists at ${BACKUP_DIR}/${base}, not overwriting."
          fi
        }

        ensure_flag_in_manifest() {
          # If flag already set with correct value, do nothing
          if grep -qE "[[:space:]]${FLAG_NAME}=${ROOT_CA_PATH}([[:space:]]|$|\"|')" "${MANIFEST}"; then
            echo "Manifest already contains ${FLAG_VALUE}, no change needed."
            return
          fi

          # If flag present with wrong value, replace it
          if grep -q "${FLAG_NAME}=" "${MANIFEST}"; then
            echo "Updating existing ${FLAG_NAME} value in manifest to ${ROOT_CA_PATH}."
            # Replace any existing --root-ca-file=<something> token with the desired one
            # Handles lines in args: [ "...", "--root-ca-file=/old", ... ]
            sed -i -E "s#${FLAG_NAME}=[^\"'[:space:]]*#${FLAG_VALUE}#g" "${MANIFEST}"
            return
          fi

          # Otherwise, add the flag under the command/args section.
          # Try to append to an existing args: list if present.
          if grep -q '^\s*args:\s*$' "${MANIFEST}"; then
            echo "Adding ${FLAG_VALUE} to existing args list in manifest."
            # Insert a new "- --root-ca-file=..." line after the 'args:' line
            awk -v flag="${FLAG_VALUE}" '
              /^\s*args:\s*$/ && !added {
                print $0
                print "    - " flag
                added=1
                next
              }
              { print $0 }
            ' "${MANIFEST}" > "${MANIFEST}.tmp"
            mv "${MANIFEST}.tmp" "${MANIFEST}"
          else
            # Fallback: append a minimal args section with the flag under the container spec.
            echo "No args list found; appending args section with ${FLAG_VALUE}."
            awk -v flag="${FLAG_VALUE}" '
              /- name: kube-controller-manager/ && !added {
                print $0
                getline
                print $0
                print "    args:"
                print "      - " flag
                added=1
                next
              }
              { print $0 }
            ' "${MANIFEST}" > "${MANIFEST}.tmp"
            mv "${MANIFEST}.tmp" "${MANIFEST}"
          fi
        }

        wait_for_pod_restart() {
          echo "Waiting up to 120 seconds for kube-controller-manager static pod to restart..."
          local timeout=120
          local waited=0
          while [ "${waited}" -lt "${timeout}" ]; do
            if /bin/ps -ef | grep '[k]ube-controller-manager' >/dev/null 2>&1; then
              # Extra small delay to allow full startup
              sleep 5
              return
            fi
            sleep 5
            waited=$((waited + 5))
          done
          echo "WARNING: kube-controller-manager process not detected after ${timeout} seconds." >&2
        }

        verify_process_flag() {
          echo "Verifying that kube-controller-manager is running with ${FLAG_VALUE} ..."
          if /bin/ps -ef | grep '[k]ube-controller-manager' | grep -q "${FLAG_VALUE}"; then
            echo "PASS: kube-controller-manager process includes ${FLAG_VALUE}"
            /bin/ps -ef | grep '[k]ube-controller-manager'
            return 0
          else
            echo "FAIL: kube-controller-manager process does not include ${FLAG_VALUE}" >&2
            /bin/ps -ef | grep '[k]ube-controller-manager' || true
            return 1
          fi
        }

        main() {
          require_root
          check_files
          backup_manifest
          ensure_flag_in_manifest

          echo "Manifest updated (or already compliant). kubelet will restart the static pod automatically."
          # Give kubelet some time to notice and restart; then verify.
          wait_for_pod_restart
          verify_process_flag
        }

        main "$@"
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/admin/kube-controller-manager/](https://kubernetes.io/docs/admin/kube-controller-manager/)
