API Server Service Account Lookup Should Be True
More Info:
Verifies that --service-account-lookup is set to true so service account tokens are validated against etcd, ensuring deleted tokens are rejected.
Risk Level
High
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every control plane node, open the API server static pod manifest for editing:
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml -
In the
command:orargs:list forkube-apiserver, either:-
Add the flag if missing:
- --service-account-lookup=true -
Or, if a line like this exists, change it to
true:- --service-account-lookup=false -
Alternatively, you may delete the entire
- --service-account-lookup=...line to rely on the secure default.
-
-
Save the file and exit the editor. The kubelet will automatically detect the manifest change and restart the
kube-apiserverstatic pod on that control plane node. -
Wait 30–60 seconds for the API server pod to restart, then verify the process on that node includes the correct flag (or that the flag is absent, using the default):
/bin/ps -ef | grep kube-apiserver | grep -v grep -
In the output, confirm either:
--service-account-lookup=trueis present in the command line, or- there is no
--service-account-lookup=flag at all.
Using kubectl
kubectl cannot modify the API server’s static pod manifest or its process flags. This setting must be changed directly on each control plane node in /etc/kubernetes/manifests/kube-apiserver.yaml; see the Manual Steps section for the required host-level changes.
Automation
#!/usr/bin/env bash
#
# Remediation for CIS Kubernetes 1.2.21:
# Ensure --service-account-lookup is set to true for kube-apiserver
#
# Run on: every control plane node
# Requirements: bash, grep, sed, awk, docker or crictl (or none; only for live check)
#
# This script:
# 1. Backs up /etc/kubernetes/manifests/kube-apiserver.yaml
# 2. Ensures --service-account-lookup=true is present exactly once
# 3. Relies on the static pod mechanism to restart kube-apiserver
# 4. Verifies the running kube-apiserver process flags
set -euo pipefail
MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-cis-1.2.21"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
echo "[INFO] CIS 1.2.21 remediation starting"
if [ ! -f "$MANIFEST" ]; then
echo "[ERROR] Manifest $MANIFEST not found on this node; is this a control plane node?"
exit 1
fi
mkdir -p "$BACKUP_DIR"
BACKUP_FILE="${BACKUP_DIR}/kube-apiserver.yaml.${TIMESTAMP}"
cp -p "$MANIFEST" "$BACKUP_FILE"
echo "[INFO] Backup created at $BACKUP_FILE"
# Check current state in manifest
if grep -qE '^\s*-?\s*--service-account-lookup(=|$)' "$MANIFEST"; then
echo "[INFO] Existing --service-account-lookup flag found in manifest; normalizing to true"
# Normalize any existing occurrences to --service-account-lookup=true
# Handles both "--service-account-lookup" and "--service-account-lookup=false/true"
tmpfile="$(mktemp)"
awk '
{
gsub(/--service-account-lookup(=true|=false)?/, "--service-account-lookup=true")
print
}
' "$MANIFEST" > "$tmpfile"
mv "$tmpfile" "$MANIFEST"
else
echo "[INFO] No --service-account-lookup flag found; adding --service-account-lookup=true"
# Insert flag in the command list under containers[].command
# Heuristic: append as a new "- --service-account-lookup=true" line
# after the last existing kube-apiserver flag line.
tmpfile="$(mktemp)"
inserted=0
while IFS= read -r line; do
echo "$line" >> "$tmpfile"
# Detect likely flag lines (indented "- --something")
if [[ "$line" =~ ^[[:space:]]*-[[:space:]]*--[a-zA-Z0-9-]+=?.* ]]; then
last_flag_line="$line"
fi
done < "$MANIFEST"
if [ -n "${last_flag_line:-}" ]; then
# Rebuild with insertion after the last flag line
: > "$tmpfile"
while IFS= read -r line; do
echo "$line" >> "$tmpfile"
if [ "$line" = "$last_flag_line" ] && [ "$inserted" -eq 0 ]; then
# Preserve indentation from last_flag_line
indent="$(printf '%s\n' "$last_flag_line" | sed -E 's/^([[:space:]]*).*/\1/')"
echo "${indent}- --service-account-lookup=true" >> "$tmpfile"
inserted=1
fi
done < "$MANIFEST"
mv "$tmpfile" "$MANIFEST"
else
echo "[WARN] Could not auto-locate flag section; appending at end of file"
echo " - --service-account-lookup=true" >> "$MANIFEST"
rm -f "$tmpfile"
fi
fi
echo "[INFO] Updated $MANIFEST. Static pod kube-apiserver will restart automatically."
echo "[INFO] Waiting for kube-apiserver to restart with new flags..."
# Wait up to 120s for process with updated flag
end=$((SECONDS + 120))
success=0
while [ $SECONDS -lt $end ]; do
# shellcheck disable=SC2009
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--service-account-lookup=true"; then
success=1
break
fi
sleep 5
done
if [ "$success" -ne 1 ]; then
echo "[ERROR] kube-apiserver process did not show --service-account-lookup=true within timeout."
echo "[INFO] Current kube-apiserver processes:"
/bin/ps -ef | grep kube-apiserver | grep -v grep || true
exit 2
fi
echo "[INFO] Verification succeeded: kube-apiserver running with --service-account-lookup=true"
echo "[INFO] CIS 1.2.21 remediation completed successfully"