Skip to main content

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

Manual Steps
  1. 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.

  1. If the node also uses a systemd drop-in with kubelet flags, ensure there is no conflicting --anonymous-auth flag. 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.

  1. Reload systemd configuration on the worker node:
sudo systemctl daemon-reload
  1. Restart the kubelet on the worker node (this will temporarily impact node status and pod scheduling on this node):
sudo systemctl restart kubelet.service
  1. 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=true flag present, and/or
  • if --anonymous-auth appears, 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."

Additional Reading: