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 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

Manual Steps
  1. Check current Kubelet configuration (every worker node)

    sudo grep -n 'anonymous' /var/lib/kubelet/config.yaml || echo "no anonymous section found"
  2. Edit the Kubelet config file to disable anonymous auth (every worker node)
    Open the file:

    sudo vi /var/lib/kubelet/config.yaml

    In the authentication section, ensure it looks like this (add or modify as needed):

    authentication:
    anonymous:
    enabled: false

    Save and exit.

  3. If the node is using Kubelet flags, ensure the flag is set (every worker node, if applicable)

    sudo grep -n 'anonymous-auth' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf || echo "flag not set"
    sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

    In the KUBELET_SYSTEM_PODS_ARGS (or equivalent) line, add or ensure:

    --anonymous-auth=false

    Save and exit.

  4. Reload systemd and restart kubelet (every worker node)

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
  5. Verify kubelet is running with anonymous auth disabled (every worker node)

    /bin/ps -fC kubelet
    sudo grep -n 'authentication' -n /var/lib/kubelet/config.yaml
    sudo grep -n 'anonymous-auth' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf 2>/dev/null || echo "flag not in systemd unit (config file likely in use)"

    Confirm either the config file has authentication: anonymous: enabled: false or the kubelet process includes --anonymous-auth=false.

Using kubectl

Using kubectl cannot modify the kubelet’s --anonymous-auth setting or the /var/lib/kubelet/config.yaml file on worker nodes; this must be fixed directly on each node’s host configuration (systemd unit and/or kubelet config file). See the Manual Steps section for the required on-node changes and how to restart kubelet safely.

Automation
#!/usr/bin/env bash
#
# Hardens kubelet by disabling anonymous auth via /var/lib/kubelet/config.yaml
# Applies to: every worker node
# Usage: run as root on each worker node (e.g. via SSH or a config management tool)

set -euo pipefail

CONFIG_FILE="/var/lib/kubelet/config.yaml"
BACKUP_DIR="/var/lib/kubelet/backup-$(date -u +%Y%m%dT%H%M%SZ)"
NEED_RESTART=0

echo "[INFO] Ensuring kubelet anonymous auth is disabled using ${CONFIG_FILE}"

if [[ ! -f "${CONFIG_FILE}" ]]; then
echo "[ERROR] Kubelet config file ${CONFIG_FILE} not found. This script expects kubelet to be using a config file."
echo "[ERROR] If your kubelet is configured only via flags, set --anonymous-auth=false in the systemd unit as per CIS guidance."
exit 1
fi

mkdir -p "${BACKUP_DIR}"
cp -a "${CONFIG_FILE}" "${BACKUP_DIR}/config.yaml"

echo "[INFO] Backed up current config to ${BACKUP_DIR}/config.yaml"

# Ensure yq is available for safe YAML editing; install guidance if missing
if ! command -v yq >/dev/null 2>&1; then
echo "[ERROR] This script requires 'yq' (https://mikefarah.gitbook.io/yq/) to edit YAML safely."
echo " Install yq on this node, then re-run the script."
exit 1
fi

# Detect current value (if any)
CURRENT_VAL="$(yq '.authentication.anonymous.enabled // "unset"' "${CONFIG_FILE}" || echo "unset")"

if [[ "${CURRENT_VAL}" == "false" ]]; then
echo "[INFO] authentication.anonymous.enabled is already set to false. No change needed."
else
echo "[INFO] Setting authentication.anonymous.enabled to false (was: ${CURRENT_VAL})"
# This creates the authentication/anonymous structure if it does not exist
TMP_FILE="${CONFIG_FILE}.tmp.$$"
yq '.authentication.anonymous.enabled = false' "${CONFIG_FILE}" > "${TMP_FILE}"
mv "${TMP_FILE}" "${CONFIG_FILE}"
NEED_RESTART=1
fi

# Restart kubelet if we changed config
if [[ "${NEED_RESTART}" -eq 1 ]]; then
echo "[INFO] Restarting kubelet to apply configuration change"
systemctl daemon-reload
systemctl restart kubelet.service
sleep 5
else
echo "[INFO] Skipping kubelet restart; no configuration changes made."
fi

# Verification: confirm kubelet is running and anonymous-auth is effectively disabled
echo "[INFO] Verifying kubelet process is running"
if ! /bin/ps -fC kubelet >/dev/null 2>&1; then
echo "[ERROR] kubelet process not found after restart. Check 'systemctl status kubelet' for details."
exit 1
fi

echo "[INFO] kubelet process is running. Verifying config value:"
VERIFY_VAL="$(yq '.authentication.anonymous.enabled // "unset"' "${CONFIG_FILE}" || echo "unset")"
echo "[INFO] /var/lib/kubelet/config.yaml -> authentication.anonymous.enabled = ${VERIFY_VAL}"

if [[ "${VERIFY_VAL}" != "false" ]]; then
echo "[ERROR] Expected authentication.anonymous.enabled=false in ${CONFIG_FILE}, but found '${VERIFY_VAL}'."
exit 1
fi

echo "[INFO] Anonymous auth is disabled in kubelet config on this node."
echo "[INFO] To complete remediation, run this script on every worker node."

Additional Reading: