Skip to main content

Ensure Client Ca File Argument Is Set 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 AKS
  • CIS Critical Security Controls v8
  • 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

Manual Steps
  1. On every worker node, open the kubelet config file and configure the client CA file:
sudo vi /var/lib/kubelet/config.yaml

Under the authentication section, ensure the following (create the section if missing), pointing clientCAFile to your actual CA bundle path, for example /etc/kubernetes/pki/ca.crt:

authentication:
x509:
clientCAFile: "/etc/kubernetes/pki/ca.crt"
  1. If your kubelet also uses command-line flags, ensure --client-ca-file is set consistently in the kubelet systemd drop-in (adjust the path only if different in your environment):
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

In the line defining extra args (for example KUBELET_AUTHZ_ARGS= or KUBELET_KUBECONFIG_ARGS= / KUBELET_EXTRA_ARGS=), add or update:

--client-ca-file=/etc/kubernetes/pki/ca.crt
  1. Reload systemd configuration and restart kubelet on the same worker node to apply the changes:
sudo systemctl daemon-reload
sudo systemctl restart kubelet.service
  1. Verify on that worker node that kubelet is running with the correct configuration by inspecting the process command line:
/bin/ps -fC kubelet

Confirm either:

  • The output includes --client-ca-file=/etc/kubernetes/pki/ca.crt, or
  • You are confident kubelet is loading /var/lib/kubelet/config.yaml that contains the authentication.x509.clientCAFile setting pointing to your chosen CA file.
Using kubectl

kubectl cannot modify kubelet host-level configuration such as /var/lib/kubelet/config.yaml or systemd units on worker nodes. To remediate this finding, make the changes directly on each worker node as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Remediate CIS AKS 3.2.3: Ensure kubelet client CA file is configured
#
# - Sets authentication.x509.clientCAFile in /var/lib/kubelet/config.yaml
# - Reloads and restarts kubelet if needed
# - Verifies that kubelet is running with the configured client CA
#
# RUN ON: every worker node (as root)

set -euo pipefail

KUBELET_CONFIG="/var/lib/kubelet/config.yaml"
SYSTEMD_UNIT="kubelet.service"
CLIENT_CA_FILE="/etc/kubernetes/pki/ca.crt" # adjust if your CA is elsewhere

# --- Preconditions ---

if [[ $EUID -ne 0 ]]; then
echo "ERROR: Run this script as root." >&2
exit 1
fi

if [[ ! -f "$CLIENT_CA_FILE" ]]; then
echo "ERROR: Client CA file not found at $CLIENT_CA_FILE" >&2
echo "Update CLIENT_CA_FILE in this script to the correct CA path, then re-run." >&2
exit 1
fi

if [[ ! -f "$KUBELET_CONFIG" ]]; then
echo "ERROR: Kubelet config file not found at $KUBELET_CONFIG" >&2
exit 1
fi

if ! command -v python3 >/dev/null 2>&1; then
echo "ERROR: python3 is required for safe YAML editing." >&2
exit 1
fi

# --- Backup ---

BACKUP_DIR="/var/backups/kubelet_cis_3_2_3"
mkdir -p "$BACKUP_DIR"
cp -a "$KUBELET_CONFIG" "${BACKUP_DIR}/config.yaml.$(date +%Y%m%d%H%M%S)"

# --- Ensure clientCAFile in kubelet config.yaml (idempotent) ---

TMP_CONFIG="$(mktemp)"
python3 - "$KUBELET_CONFIG" "$CLIENT_CA_FILE" > "$TMP_CONFIG" << 'PYCODE'
import sys, os, yaml

cfg_path = sys.argv[1]
ca_path = sys.argv[2]

with open(cfg_path, "r") as f:
data = yaml.safe_load(f) or {}

# Navigate/create nested keys: authentication -> x509 -> clientCAFile
auth = data.get("authentication") or {}
x509 = auth.get("x509") or {}

changed = (x509.get("clientCAFile") != ca_path)
x509["clientCAFile"] = ca_path
auth["x509"] = x509
data["authentication"] = auth

yaml.safe_dump(data, sys.stdout, default_flow_style=False)
PYCODE

if ! cmp -s "$TMP_CONFIG" "$KUBELET_CONFIG"; then
mv "$TMP_CONFIG" "$KUBELET_CONFIG"
CONFIG_CHANGED=1
echo "Updated $KUBELET_CONFIG with authentication.x509.clientCAFile=$CLIENT_CA_FILE"
else
rm -f "$TMP_CONFIG"
CONFIG_CHANGED=0
echo "$KUBELET_CONFIG already has authentication.x509.clientCAFile=$CLIENT_CA_FILE"
fi

# --- Restart kubelet if needed ---

if [[ "$CONFIG_CHANGED" -eq 1 ]]; then
echo "Reloading systemd and restarting kubelet..."
systemctl daemon-reload
systemctl restart "$SYSTEMD_UNIT"
else
echo "No kubelet restart needed; configuration already compliant."
fi

# --- Verification (adapted from audit: ps -fC kubelet) ---

echo "Verifying kubelet is running and client CA is configured..."

if ! ps -fC kubelet >/dev/null 2>&1; then
echo "ERROR: kubelet process not found after restart." >&2
systemctl status "$SYSTEMD_UNIT" --no-pager >&2 || true
exit 1
fi

# Confirm the config file still has the correct setting
if ! grep -q "clientCAFile: *${CLIENT_CA_FILE}" "$KUBELET_CONFIG"; then
echo "ERROR: clientCAFile not correctly set in $KUBELET_CONFIG" >&2
exit 1
fi

echo "SUCCESS: kubelet is running (ps -fC kubelet) and authentication.x509.clientCAFile is set to $CLIENT_CA_FILE in $KUBELET_CONFIG."

Additional Reading: