Ensure Client Ca File Argument Is Set As Appropriate
More Info:
Enable Kubelet authentication using certificates.
Risk Level
Low
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS GKE
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every worker node, open the kubelet config file and configure the client CA file:
sudo vi /var/lib/kubelet/config.yamlEnsure the following section exists and is set to the correct CA certificate path (create the nested keys if missing):
authentication:x509:clientCAFile: "/etc/kubernetes/pki/ca.crt"Replace
/etc/kubernetes/pki/ca.crtwith the actual path to your client CA file if different. -
Confirm the CA file exists and is readable by the kubelet user (usually root):
sudo ls -l /etc/kubernetes/pki/ca.crtsudo file /etc/kubernetes/pki/ca.crt -
Reload systemd and restart the kubelet so the new configuration takes effect:
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
Verify the kubelet process is running and pick its PID:
/bin/ps -fC kubeletConfirm that the kubelet is running without crash-looping (the command should show a stable kubelet process).
-
(Optional, if you also use command-line arguments instead of or in addition to the config file) On every worker node, edit the kubelet systemd drop-in to ensure
--client-ca-fileis present in the KUBELET_AUTHZ_ARGS:sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.confIn the
Environment=line that definesKUBELET_AUTHZ_ARGS, ensure it contains:Environment="KUBELET_AUTHZ_ARGS=--client-ca-file=/etc/kubernetes/pki/ca.crt"Then reload and restart again:
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
Final verification on every worker node:
/bin/ps -fC kubeletIf you are using only the config file, the presence of
authentication.x509.clientCAFilein/var/lib/kubelet/config.yamltogether with a healthy kubelet process satisfies the control; if you are also using flags, confirm--client-ca-file=/etc/kubernetes/pki/ca.crtappears in the kubelet command line output.
Using kubectl
kubectl cannot configure the kubelet’s --client-ca-file or edit /var/lib/kubelet/config.yaml, because these are host-level settings managed on each worker node. To remediate this finding, make the changes directly on the nodes as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Purpose: Ensure kubelet is configured with a client CA file for x509 auth
# Scope: Run on every worker node (as root)
#
# Behavior:
# - Ensures authentication.x509.clientCAFile is set in /var/lib/kubelet/config.yaml
# - Leaves an existing non-empty clientCAFile unchanged
# - Restarts kubelet only if a change is made
# - Verifies kubelet is running with a client CA configured
set -euo pipefail
KUBELET_CONFIG="/var/lib/kubelet/config.yaml"
# Adjust this path if your cluster uses a different CA location
DEFAULT_CLIENT_CA_FILE="/etc/kubernetes/pki/ca.crt"
BACKUP_SUFFIX=".pre_clientcafile.bak_$(date +%Y%m%d%H%M%S)"
require_root() {
if [[ "$(id -u)" -ne 0 ]]; then
echo "ERROR: This script must be run as root on each worker node." >&2
exit 1
fi
}
check_file_exists() {
local f="$1"
if [[ ! -f "$f" ]]; then
echo "ERROR: Required file not found: $f" >&2
exit 1
fi
}
ensure_yq() {
if ! command -v yq >/dev/null 2>&1; then
echo "ERROR: This script requires 'yq' (YAML processor) to modify $KUBELET_CONFIG safely." >&2
echo "Install v4+ of 'yq' (https://github.com/mikefarah/yq) and re-run." >&2
exit 1
fi
}
backup_file_if_needed() {
local f="$1"
if [[ -f "$f" ]]; then
cp -p "$f" "${f}${BACKUP_SUFFIX}"
echo "Backup created: ${f}${BACKUP_SUFFIX}"
fi
}
configure_kubelet_client_ca() {
local cfg="$1"
local ca_file="$2"
local changed=0
# If authentication.x509.clientCAFile is already set and non-empty, do nothing
local current
current="$(yq '.authentication.x509.clientCAFile // ""' "$cfg")"
if [[ -n "$current" && "$current" != "null" ]]; then
echo "Existing clientCAFile detected in $cfg: $current"
return 0
fi
echo "Setting authentication.x509.clientCAFile to $ca_file in $cfg"
backup_file_if_needed "$cfg"
yq -i ".authentication.x509.clientCAFile = \"$ca_file\"" "$cfg"
changed=1
return $changed
}
restart_kubelet_if_needed() {
local changed="$1"
if [[ "$changed" -eq 1 ]]; then
echo "Reloading systemd and restarting kubelet..."
systemctl daemon-reload
systemctl restart kubelet.service
else
echo "No kubelet config change detected; not restarting kubelet."
fi
}
verify() {
echo "Verification: checking kubelet process and effective client CA setting..."
echo "kubelet process:"
/bin/ps -fC kubelet || {
echo "ERROR: kubelet process not found after changes." >&2
exit 1
}
# Show relevant flags for manual confirmation
echo
echo "kubelet command-line (for reference):"
/bin/ps -o args= -C kubelet || true
# Show effective YAML setting
if [[ -f "$KUBELET_CONFIG" ]]; then
echo
echo "Configured authentication.x509.clientCAFile in $KUBELET_CONFIG:"
yq '.authentication.x509.clientCAFile' "$KUBELET_CONFIG"
else
echo
echo "WARNING: $KUBELET_CONFIG not found during verification."
fi
}
main() {
require_root
check_file_exists "$KUBELET_CONFIG"
check_file_exists "$DEFAULT_CLIENT_CA_FILE"
ensure_yq
local changed=0
if configure_kubelet_client_ca "$KUBELET_CONFIG" "$DEFAULT_CLIENT_CA_FILE"; then
# Return code 0 either way; detect change by comparing config before/after
# Simple heuristic: if backup exists and differs, assume change
if [[ -f "${KUBELET_CONFIG}${BACKUP_SUFFIX}" ]] && \
! diff -q "${KUBELET_CONFIG}${BACKUP_SUFFIX}" "$KUBELET_CONFIG" >/dev/null 2>&1; then
changed=1
fi
fi
restart_kubelet_if_needed "$changed"
verify
}
main "$@"