Skip to main content

Kubelet Rotate Certificates Argument Not Set To False

More Info:​

The kubelet --rotate-certificates argument should not be set to false so the kubelet automatically rotates its client certificates. Disabling rotation increases the risk of using expired or compromised credentials.

Risk Level​

High

Address​

Security

Compliance Standards​

  • CIS OKE

Triage and Remediation​

Remediation​

Manual Steps
  1. On every worker node, open the kubelet systemd drop-in config for editing:

    sudo vi /etc/systemd/system/kubelet.service.d/00-default.conf
  2. In that file, locate the ExecStart= line. If it contains --rotate-certificates=false, remove =false so it reads --rotate-certificates (or, if the flag is missing entirely, add it), for example:

    ExecStart=/usr/bin/kubelet \
    --rotate-certificates \
    ...
  3. If your kubelet instead reads its options from /etc/kubernetes/kubelet-config.json, open that file and ensure the feature is not disabled there (do not set it to false):

    sudo vi /etc/kubernetes/kubelet-config.json

    Confirm there is no line like:

    "rotateCertificates": false

    If present, either remove that line or change it to:

    "rotateCertificates": true
  4. Reload systemd and restart the kubelet so the new flag takes effect (this will restart the kubelet on this worker node):

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
  5. Confirm the kubelet is healthy on this worker node:

    sudo systemctl status kubelet -l
  6. Verify on this worker node that the kubelet process is no longer running with --rotate-certificates=false and that --rotate-certificates is present:

    /bin/ps -fC kubelet

    Inspect the command line in the output and ensure --rotate-certificates=false does not appear and --rotate-certificates (without =false) is included.

Using kubectl

kubectl cannot modify kubelet process arguments or the host-level config file /etc/kubernetes/kubelet-config.json; this setting must be changed directly on every worker node in the systemd drop-in file /etc/systemd/system/kubelet.service.d/00-default.conf. Refer to the Manual Steps section for the exact on-node edits and restart commands needed to enable certificate rotation and then re-run /bin/ps -fC kubelet for verification.

Automation
#!/usr/bin/env bash
#
# Purpose: Ensure kubelet is configured with --rotate-certificates (not set to false)
# Scope: Run on every worker node (as root)
# Safe: Idempotent; can be re-run
#

set -euo pipefail

SYSTEMD_DROPIN_DIR="/etc/systemd/system/kubelet.service.d"
SYSTEMD_DROPIN_FILE="${SYSTEMD_DROPIN_DIR}/00-default.conf"

echo "[INFO] Ensuring kubelet --rotate-certificates is configured on this node"

if [[ ! -f "${SYSTEMD_DROPIN_FILE}" ]]; then
echo "[ERROR] Systemd drop-in not found: ${SYSTEMD_DROPIN_FILE}"
echo " This script expects kubelet to be managed by systemd with that drop-in."
echo " Adjust manually according to your environment."
exit 1
fi

# Ensure drop-in directory exists (usually already does)
mkdir -p "${SYSTEMD_DROPIN_DIR}"

# Backup the existing file once
if [[ ! -f "${SYSTEMD_DROPIN_FILE}.bak" ]]; then
cp "${SYSTEMD_DROPIN_FILE}" "${SYSTEMD_DROPIN_FILE}.bak"
echo "[INFO] Backup created at ${SYSTEMD_DROPIN_FILE}.bak"
fi

# Read current content
current_content="$(cat "${SYSTEMD_DROPIN_FILE}")"

# Remove any explicit --rotate-certificates=false occurrences
modified_content="$(printf '%s\n' "${current_content}" \
| sed -E 's/(^ExecStart=.*)--rotate-certificates=false[[:space:]]*/\1/g')"

# Ensure we have a --rotate-certificates flag somewhere in ExecStart
if echo "${modified_content}" | grep -qE '^ExecStart=.*--rotate-certificates(=|[[:space:]]|$)'; then
echo "[INFO] --rotate-certificates flag already present in ExecStart."
else
echo "[INFO] Adding --rotate-certificates to kubelet ExecStart."
modified_content="$(printf '%s\n' "${modified_content}" \
| sed -E 's|^(ExecStart=.*kubelet)|\1 --rotate-certificates|')"
fi

# Only write if changed
if ! diff -q <(printf '%s\n' "${current_content}") <(printf '%s\n' "${modified_content}") >/dev/null 2>&1; then
printf '%s\n' "${modified_content}" > "${SYSTEMD_DROPIN_FILE}"
echo "[INFO] Updated ${SYSTEMD_DROPIN_FILE}"
else
echo "[INFO] No changes needed in ${SYSTEMD_DROPIN_FILE}"
fi

echo "[INFO] Reloading systemd and restarting kubelet (this will momentarily disrupt kubelet on this node)."
systemctl daemon-reload
systemctl restart kubelet.service

echo "[INFO] Verifying kubelet is running with certificate rotation enabled..."
systemctl status kubelet -l --no-pager || {
echo "[ERROR] kubelet service is not healthy after restart."
exit 1
}

echo "[INFO] Current kubelet process flags:"
/bin/ps -fC kubelet || {
echo "[ERROR] kubelet process not found."
exit 1
}

if /bin/ps -fC kubelet | grep -q -- '--rotate-certificates=false'; then
echo "[ERROR] kubelet still has --rotate-certificates=false in its arguments."
exit 1
fi

if /bin/ps -fC kubelet | grep -q -- '--rotate-certificates'; then
echo "[INFO] kubelet is running with --rotate-certificates and not set to false."
echo "[INFO] Remediation successful on this node."
exit 0
else
echo "[WARN] kubelet process does not show --rotate-certificates flag explicitly."
echo " Review ${SYSTEMD_DROPIN_FILE} and kubelet configuration manually."
exit 1
fi