> ## 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 Rotate Certificates Argument Is Enabled

### More Info:

Enable kubelet client certificate rotation.

### 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 worker node, open the kubelet config file and ensure `rotateCertificates` is not set to `false` (set it to `true` or remove the key). For example, using `vi`:
           ```bash theme={null}
           sudo vi /var/lib/kubelet/config.yaml
           ```
           In the `kubeletConfiguration` section, either remove any existing `rotateCertificates` line or set it explicitly:
           ```yaml theme={null}
           rotateCertificates: true
           ```

        2. Still on every worker node, check if kubelet is started with an explicit `--rotate-certificates=false` flag in its systemd drop-in:
           ```bash theme={null}
           sudo grep -R --no-color -n "rotate-certificates" /etc/systemd/system/kubelet.service.d /etc/systemd/system/kubelet.service 2>/dev/null || echo "no rotate-certificates flag found"
           ```

        3. If the flag is present and set to `false`, edit the systemd configuration and remove the `--rotate-certificates=false` argument completely:
           ```bash theme={null}
           sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
           ```
           In the `Environment=` or `KUBELET_CERTIFICATE_ARGS` line, delete `--rotate-certificates=false` (do not replace it with `true`; absence uses the default secure behavior).

        4. On every worker node, reload systemd configuration and restart the kubelet for changes to take effect (this will temporarily disrupt workloads on that node):
           ```bash theme={null}
           sudo systemctl daemon-reload
           sudo systemctl restart kubelet.service
           ```

        5. Verify on every worker node that kubelet is no longer running with `--rotate-certificates=false`:
           ```bash theme={null}
           /bin/ps -fC kubelet
           ```
           Inspect the command line in the output and confirm there is no `--rotate-certificates=false` flag.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify kubelet host-level configuration such as `/var/lib/kubelet/config.yaml` or the systemd unit files on worker nodes. To remediate this finding, edit the kubelet config and/or systemd service directly on each worker node as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Enable kubelet client certificate rotation on all worker nodes.
        # Usage: run on each worker node with root privileges.

        set -euo pipefail

        KUBELET_CONFIG="/var/lib/kubelet/config.yaml"
        SYSTEMD_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"

        echo "[INFO] Ensuring kubelet client certificate rotation is enabled"

        ########################################
        # 1. Update kubelet config file
        ########################################
        if [ -f "${KUBELET_CONFIG}" ]; then
          echo "[INFO] Found kubelet config: ${KUBELET_CONFIG}"

          # Backup once
          if [ ! -f "${KUBELET_CONFIG}.pre-rotate-cert-backup" ]; then
            cp -p "${KUBELET_CONFIG}" "${KUBELET_CONFIG}.pre-rotate-cert-backup"
            echo "[INFO] Backup created at ${KUBELET_CONFIG}.pre-rotate-cert-backup"
          fi

          # If rotateCertificates is explicitly set to false, change to true.
          # If set to true already, leave as-is.
          # If not present, leave file untouched (default is true).
          if grep -qE '^[[:space:]]*rotateCertificates:[[:space:]]*false[[:space:]]*$' "${KUBELET_CONFIG}"; then
            echo "[INFO] Updating rotateCertificates: false -> true in ${KUBELET_CONFIG}"
            sed -i -E 's/^([[:space:]]*rotateCertificates:[[:space:]]*)false([[:space:]]*)$/\1true\2/' "${KUBELET_CONFIG}"
          elif grep -qE '^[[:space:]]*rotateCertificates:[[:space:]]*true[[:space:]]*$' "${KUBELET_CONFIG}"; then
            echo "[INFO] rotateCertificates is already set to true in ${KUBELET_CONFIG}"
          else
            echo "[INFO] rotateCertificates not explicitly set in ${KUBELET_CONFIG}; leaving default (true) in place"
          fi
        else
          echo "[WARN] Kubelet config file ${KUBELET_CONFIG} not found; skipping file-based config"
        fi

        ########################################
        # 2. Clean up kubelet systemd arguments
        ########################################
        if [ -f "${SYSTEMD_DROPIN}" ]; then
          echo "[INFO] Found kubelet systemd drop-in: ${SYSTEMD_DROPIN}"

          # Backup once
          if [ ! -f "${SYSTEMD_DROPIN}.pre-rotate-cert-backup" ]; then
            cp -p "${SYSTEMD_DROPIN}" "${SYSTEMD_DROPIN}.pre-rotate-cert-backup"
            echo "[INFO] Backup created at ${SYSTEMD_DROPIN}.pre-rotate-cert-backup"
          fi

          # Remove any explicit --rotate-certificates=false from the file
          if grep -q -- "--rotate-certificates=false" "${SYSTEMD_DROPIN}"; then
            echo "[INFO] Removing --rotate-certificates=false from ${SYSTEMD_DROPIN}"
            # Remove the argument whether standalone or followed by space or backslash
            sed -i -E 's/[[:space:]]*--rotate-certificates=false(\\)?//g' "${SYSTEMD_DROPIN}"
          else
            echo "[INFO] No --rotate-certificates=false flag present in ${SYSTEMD_DROPIN}"
          fi
        else
          echo "[WARN] Systemd drop-in ${SYSTEMD_DROPIN} not found; skipping argument cleanup"
        fi

        ########################################
        # 3. Reload systemd and restart kubelet
        ########################################
        echo "[INFO] Reloading systemd and restarting kubelet (this will restart the kubelet process)"
        systemctl daemon-reload
        systemctl restart kubelet.service

        ########################################
        # 4. Verification
        ########################################
        echo "[INFO] Verifying kubelet process arguments"
        /bin/ps -fC kubelet || {
          echo "[ERROR] kubelet process not found after restart"
          exit 1
        }

        if /bin/ps -fC kubelet | grep -q -- "--rotate-certificates=false"; then
          echo "[ERROR] kubelet is still running with --rotate-certificates=false"
          exit 1
        fi

        echo "[INFO] kubelet is not using --rotate-certificates=false"

        # If config file exists, double-check the setting
        if [ -f "${KUBELET_CONFIG}" ]; then
          if grep -qE '^[[:space:]]*rotateCertificates:[[:space:]]*false[[:space:]]*$' "${KUBELET_CONFIG}"; then
            echo "[ERROR] rotateCertificates is still set to false in ${KUBELET_CONFIG}"
            exit 1
          fi
          echo "[INFO] Verified rotateCertificates is not set to false in ${KUBELET_CONFIG}"
        fi

        echo "[INFO] Certificate rotation setting remediated successfully on this node"
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://github.com/kubernetes/kubernetes/pull/41912](https://github.com/kubernetes/kubernetes/pull/41912)
