Skip to main content

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

Manual Steps
  1. On every control plane node, open the API server static pod manifest for editing:

    sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
  2. In the command: or args: list for kube-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.

  3. Save the file and exit the editor. The kubelet will automatically detect the manifest change and restart the kube-apiserver static pod on that control plane node.

  4. 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
  5. In the output, confirm either:

    • --service-account-lookup=true is 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"