Kubelet Rotate Server Certificates Argument Set To True
More Info:
The kubelet --rotate-server-certificates argument should be set to true so the kubelet automatically requests and rotates its serving certificates. Disabling this increases exposure to expired or compromised server certificates.
Risk Level
High
Address
Security
Compliance Standards
- CIS OKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every worker node, open the kubelet systemd drop-in config for editing:
sudo vi /etc/systemd/system/kubelet.service.d/00-default.conf -
In the
ExecStart=line, ensure the kubelet is started with--rotate-server-certificates=true. Add it if missing, or changefalsetotrue, for example:ExecStart=/usr/bin/kubelet \... \--rotate-server-certificates=true -
If the kubelet also uses a config file (e.g.
/etc/kubernetes/kubelet-config.json), check it for a conflicting setting and remove or align it. For example, if present, update this key totrueor delete it so the flag above is authoritative:sudo vi /etc/kubernetes/kubelet-config.jsonEnsure either this field is set true or absent:
"rotateServerCertificate": true -
Reload systemd and restart kubelet on the same worker node:
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
Confirm kubelet is healthy on the worker node:
sudo systemctl status kubelet -l -
Verify the argument is now set to true on the worker node (repeat on all workers):
/bin/ps -fC kubelet | grep -- --rotate-server-certificatesThe output must include
--rotate-server-certificates=true.
Using kubectl
kubectl cannot modify kubelet process flags or host-level config files such as /etc/systemd/system/kubelet.service.d/00-default.conf or /etc/kubernetes/kubelet-config.json on worker nodes. To enable --rotate-server-certificates=true, make the change directly on each worker node as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Enable kubelet --rotate-server-certificates=true on every worker node.
# Usage:
# 1) Populate NODES with worker node hostnames/IPs reachable via SSH.
# 2) Ensure passwordless sudo and SSH access.
# 3) Run this script from any admin machine: ./enable-kubelet-rotate-server-certs.sh
#
# Idempotent: safe to re-run.
set -euo pipefail
# EDIT THIS: list of worker nodes
NODES=(
worker-node-1
worker-node-2
)
SSH_OPTS="-o BatchMode=yes -o StrictHostKeyChecking=accept-new"
remote_run() {
local node="$1"; shift
ssh ${SSH_OPTS} "root@${node}" "$@"
}
for node in "${NODES[@]}"; do
echo "=== Processing node: ${node} ==="
remote_run "${node}" bash -s << 'EOF'
set -euo pipefail
UNIT_DIR="/etc/systemd/system/kubelet.service.d"
UNIT_FILE="${UNIT_DIR}/00-default.conf"
if [ ! -f "${UNIT_FILE}" ]; then
echo "ERROR: ${UNIT_FILE} not found; kubelet may be managed differently on this node."
exit 1
fi
echo "Current ${UNIT_FILE}:"
sed -n '1,160p' "${UNIT_FILE}" || true
# Ensure the drop-in has an [Service] section; if not, add one.
if ! grep -q '^\[Service\]' "${UNIT_FILE}"; then
printf '\n[Service]\n' >> "${UNIT_FILE}"
fi
# Make a backup once per run
BACKUP="${UNIT_FILE}.$(date +%Y%m%d%H%M%S).bak"
cp "${UNIT_FILE}" "${BACKUP}"
echo "Backup created at ${BACKUP}"
# Normalize into a single Environment line for editing
# (handles the common case where KUBELET_KUBECONFIG_ARGS etc. are defined)
if ! grep -q 'KUBELET_EXTRA_ARGS' "${UNIT_FILE}"; then
# If there's no extra args line, append one
cat << 'EOL' >> "${UNIT_FILE}"
Environment="KUBELET_EXTRA_ARGS="
EOL
fi
# Edit KUBELET_EXTRA_ARGS to ensure --rotate-server-certificates=true
tmpfile="$(mktemp)"
while IFS= read -r line; do
if [[ "${line}" =~ ^Environment= ]]; then
# Only touch lines with KUBELET_EXTRA_ARGS
if [[ "${line}" == *"KUBELET_EXTRA_ARGS"* ]]; then
# Remove any existing --rotate-server-certificates flags
cleaned="$(printf '%s\n' "${line}" | sed -E 's_--rotate-server-certificates(=[^" ]*)?__g')"
# Collapse multiple spaces
cleaned="$(printf '%s\n' "${cleaned}" | sed -E 's/ +/ /g')"
# Ensure it ends before final quote, then append desired flag
if [[ "${cleaned}" =~ \"$ ]]; then
cleaned="${cleaned%\"} --rotate-server-certificates=true\""
else
cleaned="${cleaned} --rotate-server-certificates=true"
fi
echo "${cleaned}" >> "${tmpfile}"
else
echo "${line}" >> "${tmpfile}"
fi
else
echo "${line}" >> "${tmpfile}"
fi
done < "${UNIT_FILE}"
mv "${tmpfile}" "${UNIT_FILE}"
echo "Updated ${UNIT_FILE}:"
sed -n '1,160p' "${UNIT_FILE}" || true
echo "Reloading systemd and restarting kubelet (this restarts the kubelet process)..."
systemctl daemon-reload
systemctl restart kubelet.service
echo "Verifying kubelet status..."
systemctl status kubelet -l --no-pager || {
echo "ERROR: kubelet service not healthy after restart."
exit 1
}
echo "Verifying kubelet process has --rotate-server-certificates=true..."
if /bin/ps -fC kubelet | grep -q -- '--rotate-server-certificates=true'; then
echo "OK: kubelet is running with --rotate-server-certificates=true"
else
echo "ERROR: kubelet is not running with --rotate-server-certificates=true"
/bin/ps -fC kubelet || true
exit 1
fi
EOF
echo "=== Node ${node} done ==="
done
echo "All nodes processed."