Ensure Anonymous Auth Argument Is Disabled
More Info:
Disable anonymous requests to the Kubelet server.
Risk Level
High
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS EKS
- 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 ensure anonymous auth is disabled:
sudo vi /var/lib/kubelet/config.yaml
Find or add the following block under authentication:
authentication:
anonymous:
enabled: false
Save and exit.
- If the node also uses a systemd drop-in with kubelet flags, ensure there is no conflicting
--anonymous-authflag. Open the file:
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
In the KUBELET_KUBEADM_ARGS (or similar) line, remove any --anonymous-auth=true flag. If you must specify it, set:
--anonymous-auth=false
Save and exit.
- Reload systemd configuration on the worker node:
sudo systemctl daemon-reload
- Restart the kubelet on the worker node (this will temporarily impact node status and pod scheduling on this node):
sudo systemctl restart kubelet.service
- Verify the kubelet process no longer allows anonymous auth by inspecting its arguments:
/bin/ps -fC kubelet
Confirm that either:
- there is no
--anonymous-auth=trueflag present, and/or - if
--anonymous-authappears, it is--anonymous-auth=false.
Using kubectl
kubectl cannot change the kubelet’s --anonymous-auth setting because it is configured on each worker node’s host (in /var/lib/kubelet/config.yaml or the kubelet systemd unit). To remediate this finding, follow the host-level instructions in the Manual Steps section on every worker node.
Automation
#!/usr/bin/env bash
#
# Remediation: Disable anonymous auth on kubelet via /var/lib/kubelet/config.yaml
# Applies to: every worker node (run locally on each node, or via SSH/Ansible)
# Idempotent: safe to run multiple times
#
set -euo pipefail
CONFIG_FILE="/var/lib/kubelet/config.yaml"
BACKUP_SUFFIX="$(date +%Y%m%d%H%M%S)"
SYSTEMD_UNIT="kubelet.service"
echo "[INFO] Ensuring kubelet anonymous auth is disabled on this node"
if [ ! -f "$CONFIG_FILE" ]; then
echo "[ERROR] Kubelet config file not found at $CONFIG_FILE"
echo "[ERROR] This script expects kubelet to be configured via $CONFIG_FILE."
echo "[ERROR] If your kubelet uses only command-line flags/systemd env, follow the Manual Steps for flag-based configuration."
exit 1
fi
# Backup once per run
cp -p "$CONFIG_FILE" "${CONFIG_FILE}.bak.${BACKUP_SUFFIX}"
echo "[INFO] Backed up $CONFIG_FILE to ${CONFIG_FILE}.bak.${BACKUP_SUFFIX}"
# Ensure the 'authentication:' block exists
if ! grep -qE '^[[:space:]]*authentication:' "$CONFIG_FILE"; then
cat <<'EOF' >>"$CONFIG_FILE"
authentication:
anonymous:
enabled: false
EOF
echo "[INFO] Added authentication.anonymous.enabled: false block to $CONFIG_FILE"
else
# Ensure 'anonymous:' exists under 'authentication:'
awk '
BEGIN { in_auth=0; anon_present=0 }
/^[[:space:]]*authentication:[[:space:]]*$/ { in_auth=1; print; next }
in_auth && /^[^[:space:]]/ { in_auth=0 }
in_auth && /^[[:space:]]*anonymous:[[:space:]]*$/ { anon_present=1 }
{ print }
END {
if (in_auth && !anon_present) {
print " anonymous:"
print " enabled: false"
}
}' "$CONFIG_FILE" >"${CONFIG_FILE}.tmp"
mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE"
echo "[INFO] Ensured authentication.anonymous block exists in $CONFIG_FILE"
# Now explicitly set enabled: false (handle various existing values/indentation)
python3 - "$CONFIG_FILE" <<'PYCODE'
import sys, io
from pathlib import Path
cfg_path = Path(sys.argv[1])
data = cfg_path.read_text()
lines = data.splitlines()
out = []
in_auth = False
in_anon = False
auth_indent = None
anon_indent = None
for line in lines:
stripped = line.lstrip()
indent = len(line) - len(stripped)
if stripped.startswith('authentication:'):
in_auth = True
auth_indent = indent
in_anon = False
out.append(line)
continue
if in_auth and indent <= (auth_indent or 0) and stripped and not stripped.startswith("#"):
in_auth = False
in_anon = False
if in_auth and stripped.startswith('anonymous:'):
in_anon = True
anon_indent = indent
out.append(line)
continue
if in_anon:
# Leaving anonymous block?
if stripped and indent <= (anon_indent or 0) and not stripped.startswith("#"):
# We already ensured block exists; just end tracking here
in_anon = False
# Replace any "enabled:" under the anonymous block
if in_anon and stripped.startswith('enabled:'):
out.append(' ' * (anon_indent + 2) + 'enabled: false')
else:
out.append(line)
cfg_path.write_text("\n".join(out) + "\n")
PYCODE
echo "[INFO] Set authentication.anonymous.enabled: false in $CONFIG_FILE"
fi
# Reload & restart kubelet to apply changes
echo "[INFO] Reloading systemd and restarting kubelet"
if command -v systemctl >/dev/null 2>&1; then
systemctl daemon-reload
systemctl restart "$SYSTEMD_UNIT"
else
echo "[WARN] systemctl not found; please restart kubelet manually to apply changes"
fi
# Verification (same host): ensure kubelet process is running and anonymous-auth is effectively disabled
echo "[INFO] Verifying kubelet process and effective anonymous-auth setting"
/bin/ps -fC kubelet || {
echo "[ERROR] kubelet process not found after restart"
exit 1
}
# Best-effort config verification: print the relevant section for human review
echo "[INFO] Current authentication.anonymous section in $CONFIG_FILE:"
grep -n -A3 -B1 'authentication:' "$CONFIG_FILE" | sed -n '1,40p'
echo "[INFO] Verification step: kubelet is running. Confirm that the 'enabled' field under authentication.anonymous is set to false above."