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​

  • CIS Kubernetes

Triage and Remediation​

Remediation​

Manual Steps
  1. On every control plane node, back up the API server manifest before editing:

    sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak.$(date +%F-%H%M%S)
  2. On every control plane node, open the API server static pod manifest for editing:

    sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
  3. In the kube-apiserver container command or args section, ensure the flag is present and set to false (add it if missing), for example:

    - kube-apiserver
    - --anonymous-auth=false

    Save and exit. Editing this file will cause the kubelet to restart the API server pod automatically.

  4. Wait for the kube-apiserver pod to be recreated and become Ready (from any machine with kubectl access):

    kubectl get pods -n kube-system -l component=kube-apiserver -o wide
  5. On every control plane node, verify the running kube-apiserver process now includes --anonymous-auth=false:

    /bin/ps -ef | grep kube-apiserver | grep -v grep
Using kubectl

kubectl cannot modify kube-apiserver process flags or host-level files, so it cannot be used to set --anonymous-auth=false. To remediate this finding, you must edit the static pod manifest /etc/kubernetes/manifests/kube-apiserver.yaml directly on every control plane node; see the Manual Steps section for the exact procedure.

Automation
#!/usr/bin/env bash
#
# Automation: Disable anonymous auth on kube-apiserver (--anonymous-auth=false)
#
# Run on: every control plane node (as root)
# Effect: Editing /etc/kubernetes/manifests/kube-apiserver.yaml will restart the kube-apiserver
# because it is a static Pod managed by kubelet.

set -euo pipefail

APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-$(date +%Y%m%d)"
PARAM="--anonymous-auth=false"

echo "==> Ensuring kube-apiserver anonymous-auth is disabled"

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

if [[ ! -f "${APISERVER_MANIFEST}" ]]; then
echo "ERROR: kube-apiserver manifest not found at ${APISERVER_MANIFEST}." >&2
exit 1
fi

mkdir -p "${BACKUP_DIR}"

backup_file="${BACKUP_DIR}/kube-apiserver.yaml.$(date +%H%M%S)"
cp -a "${APISERVER_MANIFEST}" "${backup_file}"
echo "Backup created at ${backup_file}"

# Idempotently ensure --anonymous-auth=false is present and not overridden

# 1) Remove any existing --anonymous-auth=... occurrences to avoid conflicts
tmpfile="$(mktemp)"
trap 'rm -f "${tmpfile}"' EXIT

sed -E 's/--anonymous-auth=[^[:space:]]+//g' "${APISERVER_MANIFEST}" > "${tmpfile}"

# 2) Ensure there is exactly one --anonymous-auth=false in the container args.
# We will append it in the args: list if not already present.
if ! grep -q -- "${PARAM}" "${tmpfile}"; then
# Insert into the first occurrence of " - --" style arg list under kube-apiserver container.
# This is conservative and keeps indentation.
if grep -qE '^\s*- --' "${tmpfile}"; then
# Append a new arg line right after the first existing arg line.
awk -v param="${PARAM}" '
BEGIN {added=0}
{
print $0
if (!added && $0 ~ /^[[:space:]]*- --/) {
sub(/^- /,"",$0) # no-op; just to show we found it
print gensub(/^([[:space:]]*)- .*/, "\\1- " param, 1)
added=1
}
}
END {
if (!added) {
# Fallback: print at end as a top-level arg (unlikely path)
print "- " param
}
}
' "${tmpfile}" > "${tmpfile}.new"
mv "${tmpfile}.new" "${tmpfile}"
else
# No recognizable args list; append at end of file as a last resort.
echo "- ${PARAM}" >> "${tmpfile}"
fi
fi

# 3) Move the updated manifest into place atomically
cp -a "${tmpfile}" "${APISERVER_MANIFEST}"
chmod 600 "${APISERVER_MANIFEST}" || true

echo "Updated ${APISERVER_MANIFEST} with ${PARAM}"

# 4) Wait for kube-apiserver to restart and run with the new flag.
# We poll the process command line until it shows --anonymous-auth=false.
echo "Waiting for kube-apiserver to run with ${PARAM} ..."

RETRIES=30
SLEEP_SECONDS=10
success=0

for i in $(seq 1 "${RETRIES}"); do
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "${PARAM}"; then
success=1
break
fi
echo " Attempt ${i}/${RETRIES}: kube-apiserver not yet running with ${PARAM}, retrying in ${SLEEP_SECONDS}s..."
sleep "${SLEEP_SECONDS}"
done

if [[ "${success}" -ne 1 ]]; then
echo "WARNING: kube-apiserver process did not show ${PARAM} after ${RETRIES} attempts." >&2
echo "Please check kubelet and kube-apiserver status manually."
exit 1
fi

echo "Verification: kube-apiserver is running with ${PARAM}"
/bin/ps -ef | grep kube-apiserver | grep -v grep

echo "==> Completed: anonymous auth disabled on this control plane node."

Additional Reading:​