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
Remediation
Manual Steps
-
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) -
On every control plane node, open the API server static pod manifest for editing:
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml -
In the
kube-apiservercontainercommandorargssection, ensure the flag is present and set to false (add it if missing), for example:- kube-apiserver- --anonymous-auth=falseSave and exit. Editing this file will cause the kubelet to restart the API server pod automatically.
-
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 -
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."