> ## 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.

# Kubelet RotateKubeletServerCertificate Argument Set To True

### More Info:

The RotateKubeletServerCertificate feature gate enables automatic rotation of the kubelet serving certificate. Enabling it ensures the kubelets server certificate is renewed before it expires.

### Risk Level

High

### 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 current kube-controller-manager manifest:
           ```bash theme={null}
           sudo cp -a /etc/kubernetes/manifests/kube-controller-manager.yaml /etc/kubernetes/manifests/kube-controller-manager.yaml.backup
           ```

        2. Edit the kube-controller-manager static pod manifest to configure the feature gate:
           ```bash theme={null}
           sudo sed -i '/- kube-controller-manager/a\    - --feature-gates=RotateKubeletServerCertificate=true' /etc/kubernetes/manifests/kube-controller-manager.yaml
           ```
           If a `--feature-gates=` argument already exists, edit that line instead (with a text editor such as `sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml`) to ensure it includes `RotateKubeletServerCertificate=true` in the comma-separated list.

        3. Wait for the kube-controller-manager pod to be recreated (editing any file under `/etc/kubernetes/manifests` causes an automatic restart via the kubelet). You can watch for the new pod on any machine with `kubectl` access:
           ```bash theme={null}
           kubectl -n kube-system get pods -l component=kube-controller-manager -w
           ```

        4. Verify on each control plane node that the kube-controller-manager process now has the correct feature gate set:
           ```bash theme={null}
           /bin/ps -ef | grep kube-controller-manager | grep -v grep
           ```
           Confirm the output includes `--feature-gates=RotateKubeletServerCertificate=true` (or a `--feature-gates=` value that contains `RotateKubeletServerCertificate=true`).
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot be used to enable `RotateKubeletServerCertificate` because this setting is controlled via the kube-controller-manager static pod manifest on each control plane node. To remediate, edit `/etc/kubernetes/manifests/kube-controller-manager.yaml` on every control plane node as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Enable RotateKubeletServerCertificate via kube-controller-manager feature-gate
        # Scope: run on every control plane node (as root)
        # Safe to re-run (idempotent). Requires: bash, sed, grep, systemctl (for static pod restart behavior note only).
        #

        set -euo pipefail

        MANIFEST="/etc/kubernetes/manifests/kube-controller-manager.yaml"

        echo "[INFO] Ensuring RotateKubeletServerCertificate=true on feature-gates in ${MANIFEST}"

        if [ ! -f "${MANIFEST}" ]; then
          echo "[ERROR] Controller manager manifest not found at ${MANIFEST}. Are you on a control plane node?"
          exit 1
        fi

        # Backup once
        if [ ! -f "${MANIFEST}.pre-rotatekubeletservercertificate.bak" ]; then
          cp "${MANIFEST}" "${MANIFEST}.pre-rotatekubeletservercertificate.bak"
          echo "[INFO] Backup created: ${MANIFEST}.pre-rotatekubeletservercertificate.bak"
        fi

        # Normalize file to avoid sed issues with CRLF
        dos2unix "${MANIFEST}" >/dev/null 2>&1 || true

        # Function to check if RotateKubeletServerCertificate=true is already present on a given line
        has_rotate_gate() {
          # $1 = line
          grep -q -- "--feature-gates=" <<<"$1" && \
            grep -q "RotateKubeletServerCertificate=true" <<<"$1"
        }

        # Detect if any --feature-gates arg exists
        if grep -q -- "--feature-gates=" "${MANIFEST}"; then
          echo "[INFO] Existing --feature-gates flag found; ensuring RotateKubeletServerCertificate=true is set"

          # Update any existing --feature-gates container args that contain RotateKubeletServerCertificate but not =true
          # and add RotateKubeletServerCertificate=true where missing.
          tmpfile="$(mktemp)"
          awk '
            /--feature-gates=/ {
              line=$0
              # if RotateKubeletServerCertificate is already =true, leave unmodified
              if (line ~ /RotateKubeletServerCertificate=true/) {
                print line
              } else if (line ~ /RotateKubeletServerCertificate=/) {
                # Normalize any existing RotateKubeletServerCertificate entry to true
                gsub(/RotateKubeletServerCertificate=[^,"]*/, "RotateKubeletServerCertificate=true", line)
                print line
              } else {
                # Append RotateKubeletServerCertificate=true to the feature-gates list
                # Handle common forms: --feature-gates=A=B,C=D or with surrounding quotes
                if (line ~ /--feature-gates=["'\''"][^"'\''"]*["'\''"]/ ) {
                  gsub(/(--feature-gates=["'\''"])([^"'\''"]*)(["'\''"])/, "\\1\\2,RotateKubeletServerCertificate=true\\3", line)
                } else if (line ~ /--feature-gates=[^ ,]+/) {
                  gsub(/--feature-gates=([^ ,]+)/, "--feature-gates=\\1,RotateKubeletServerCertificate=true", line)
                } else {
                  # Fallback: just append to the argument
                  gsub(/--feature-gates=/, "--feature-gates=RotateKubeletServerCertificate=true,", line)
                }
                print line
              }
              next
            }
            { print }
          ' "${MANIFEST}" > "${tmpfile}"

          mv "${tmpfile}" "${MANIFEST}"
        else
          echo "[INFO] No --feature-gates flag found; adding one with RotateKubeletServerCertificate=true"

          # Add a new --feature-gates arg under the kube-controller-manager container args
          # This handles common kubeadm-style static pod manifests.
          tmpfile="$(mktemp)"
          awk '
            /name: kube-controller-manager/ { in_kcm=1 }
            in_kcm && /args:/ && !seen_args {
              seen_args=1
              print
              print "    - --feature-gates=RotateKubeletServerCertificate=true"
              next
            }
            { print }
          ' "${MANIFEST}" > "${tmpfile}"

          # If we failed to inject (no changes), fall back to appending to any args: block under containers:
          if ! grep -q "RotateKubeletServerCertificate=true" "${tmpfile}"; then
            awk '
              /containers:/ { in_containers=1 }
              in_containers && /args:/ && !seen_args {
                seen_args=1
                print
                print "    - --feature-gates=RotateKubeletServerCertificate=true"
                next
              }
              { print }
            ' "${MANIFEST}" > "${tmpfile}"
          fi

          if ! grep -q "RotateKubeletServerCertificate=true" "${tmpfile}"; then
            echo "[ERROR] Unable to inject --feature-gates into ${MANIFEST}. Please edit manually."
            rm -f "${tmpfile}"
            exit 1
          fi

          mv "${tmpfile}" "${MANIFEST}"
        fi

        echo "[INFO] Updated ${MANIFEST}. kube-controller-manager static pod will be restarted automatically by kubelet."

        # Verification: ensure running kube-controller-manager has the correct feature-gate
        # Wait briefly for static pod restart if needed
        sleep 10

        echo "[INFO] Verifying running kube-controller-manager process on this control plane node"
        if /bin/ps -ef | grep kube-controller-manager | grep -v grep | grep -q "RotateKubeletServerCertificate=true"; then
          echo "[SUCCESS] kube-controller-manager is running with RotateKubeletServerCertificate=true in --feature-gates"
          exit 0
        else
          echo "[WARN] kube-controller-manager process does not yet show RotateKubeletServerCertificate=true."
          echo "[WARN] It may still be restarting; re-run this verification:"
          echo "       /bin/ps -ef | grep kube-controller-manager | grep -v grep"
          exit 1
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
