Kubelet Client CA File Argument Set As Appropriate
More Info:
The kubelet --client-ca-file argument should be set to enable client certificate authentication. Without a client CA, the kubelet cannot verify the identity of API clients.
Risk Level
High
Address
Security
Compliance Standards
- CIS OKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every worker node, confirm the current kubelet process arguments:
/bin/ps -fC kubeletCheck whether a
--client-ca-fileargument is present and whether it points to the intended CA (for example/etc/kubernetes/ca.crt). -
On every worker node, ensure the client CA file exists and is readable by kubelet (adjust the source path if your CA is elsewhere):
ls -l /etc/kubernetes/ca.crt || sudo cp /etc/kubernetes/pki/ca.crt /etc/kubernetes/ca.crtsudo chown root:root /etc/kubernetes/ca.crtsudo chmod 644 /etc/kubernetes/ca.crt -
On every worker node, edit the kubelet systemd drop-in to add the
--client-ca-fileargument:sudo sed -i '/KUBELET_KUBEADM_ARGS=/d' /etc/systemd/system/kubelet.service.d/00-default.confThen open the file and ensure the
ExecStartor environment line includes the flag, for example:sudo vi /etc/systemd/system/kubelet.service.d/00-default.confAdd or adjust so it contains:
[Service]Environment="KUBELET_KUBEADM_ARGS=--client-ca-file=/etc/kubernetes/ca.crt"or, if
ExecStartuses inline flags, append:ExecStart=... --client-ca-file=/etc/kubernetes/ca.crt -
On every worker node, reload systemd and restart kubelet (this will briefly disrupt workloads on that node):
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
On every worker node, confirm kubelet is healthy:
sudo systemctl status kubelet -l -
On every worker node, verify that the
--client-ca-fileargument is now set correctly:/bin/ps -fC kubeletConfirm the output shows
--client-ca-file=/etc/kubernetes/ca.crt(or your chosen CA path) in the kubelet command line.
Using kubectl
kubectl cannot configure the kubelet’s --client-ca-file flag or edit /etc/kubernetes/kubelet-config.json, because these are host-level settings managed on each worker node (systemd units and config files). To remediate this finding, make the changes directly on every worker node as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Remediates CIS OKE 3.2.3:
# Ensure kubelet is started with --client-ca-file=/etc/kubernetes/ca.crt
#
# Run on: every worker node (as root)
# Safe to re-run (idempotent).
set -euo pipefail
KUBELET_DROPIN_DIR="/etc/systemd/system/kubelet.service.d"
KUBELET_DROPIN_FILE="${KUBELET_DROPIN_DIR}/00-default.conf"
CLIENT_CA_ARG="--client-ca-file=/etc/kubernetes/ca.crt"
CA_FILE="/etc/kubernetes/ca.crt"
echo "[INFO] Starting kubelet --client-ca-file remediation"
if [[ "$(id -u)" -ne 0 ]]; then
echo "[ERROR] This script must be run as root."
exit 1
fi
if [[ ! -f "${KUBELET_DROPIN_FILE}" ]]; then
echo "[ERROR] ${KUBELET_DROPIN_FILE} not found. Adjust path or create drop-in as per your distro."
exit 1
fi
if [[ ! -f "${CA_FILE}" ]]; then
echo "[ERROR] ${CA_FILE} not found. Create or place the correct client CA certificate before rerunning."
exit 1
fi
echo "[INFO] Ensuring kubelet drop-in directory exists: ${KUBELET_DROPIN_DIR}"
mkdir -p "${KUBELET_DROPIN_DIR}"
echo "[INFO] Ensuring ${KUBELET_DROPIN_FILE} contains ${CLIENT_CA_ARG}"
# Backup once
if [[ ! -f "${KUBELET_DROPIN_FILE}.cis-3.2.3.bak" ]]; then
cp "${KUBELET_DROPIN_FILE}" "${KUBELET_DROPIN_FILE}.cis-3.2.3.bak"
fi
# Normalize file and ensure Environment line with KUBELET_EXTRA_ARGS includes the arg
tmpfile="$(mktemp)"
trap 'rm -f "${tmpfile}"' EXIT
# Read current content
cat "${KUBELET_DROPIN_FILE}" > "${tmpfile}"
# Remove any duplicate --client-ca-file arguments
sed -i 's/--client-ca-file=[^ ]*//g' "${tmpfile}"
# Ensure there is an Environment line for KUBELET_EXTRA_ARGS
if ! grep -q 'Environment=.*KUBELET_EXTRA_ARGS' "${tmpfile}"; then
# Add a basic Environment line; adapt if your distro uses a different pattern
echo 'Environment="KUBELET_EXTRA_ARGS="' >> "${tmpfile}"
fi
# Append the CLIENT_CA_ARG to KUBELET_EXTRA_ARGS, preserving existing content
# Works whether Environment= or EnvironmentContains double quotes
perl -pi -e '
if (/^Environment=.*KUBELET_EXTRA_ARGS/) {
s/"$/ '"${CLIENT_CA_ARG}"'"/ if ! /'"${CLIENT_CA_ARG//\//\\/}"'/;
}
' "${tmpfile}"
# Install updated file if changed
if ! cmp -s "${tmpfile}" "${KUBELET_DROPIN_FILE}"; then
echo "[INFO] Updating ${KUBELET_DROPIN_FILE}"
cp "${tmpfile}" "${KUBELET_DROPIN_FILE}"
else
echo "[INFO] ${KUBELET_DROPIN_FILE} already contains ${CLIENT_CA_ARG}"
fi
echo "[INFO] Reloading systemd and restarting kubelet (this will restart the kubelet on this node)"
systemctl daemon-reload
systemctl restart kubelet.service
echo "[INFO] Checking kubelet status"
systemctl status kubelet -l --no-pager || true
echo "[INFO] Verifying kubelet is running with ${CLIENT_CA_ARG}"
if /bin/ps -fC kubelet | grep -q -- "${CLIENT_CA_ARG}"; then
echo "[SUCCESS] kubelet is running with ${CLIENT_CA_ARG}"
else
echo "[FAIL] kubelet is NOT running with ${CLIENT_CA_ARG}"
echo "[INFO] Full kubelet command line:"
/bin/ps -fC kubelet || true
exit 2
fi