Skip to main content

Ensure Service Account Lookup Argument Is Set True

More Info:

Validate service account before validating token.

Risk Level

High

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. On every control plane node, open the kube-apiserver static pod manifest for editing (this will cause the API server pod to restart when saved):
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
  1. In the spec.containers[0].command list, either add or update the argument to explicitly enable service account lookup, ensuring there is only one such flag and it is set to true, for example:
- kube-apiserver
- --service-account-lookup=true
  1. If you prefer to rely on the default behavior instead of setting it explicitly, remove any existing --service-account-lookup= entry from the command list and leave it absent (do not add a replacement).

  2. Save the file and exit the editor; the kubelet will detect the manifest change and automatically restart the kube-apiserver static pod. Allow a few moments for it to restart.

  3. On the same control plane node, verify the API server process now has the correct argument set (or the flag removed if you chose to rely on the default):

/bin/ps -ef | grep kube-apiserver | grep -v grep
  1. In the output, confirm that either:
    • --service-account-lookup=true is present and there is no --service-account-lookup=false, or
    • there is no --service-account-lookup= argument at all (indicating the default applies).
Using kubectl

kubectl cannot modify the kube-apiserver static pod manifest or its process flags. To remediate this finding, you must edit /etc/kubernetes/manifests/kube-apiserver.yaml directly on every control plane node; see the Manual Steps section for exact host-level instructions.

Automation
#!/usr/bin/env bash
#
# Automation: Ensure kube-apiserver has --service-account-lookup=true
# Scope: run on every control plane node
# Effect: editing /etc/kubernetes/manifests/kube-apiserver.yaml will restart kube-apiserver (static pod)

set -euo pipefail

APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_SUFFIX=".pre_service-account-lookup_fix_$(date +%Y%m%d%H%M%S)"

echo "[INFO] Starting remediation for --service-account-lookup on host: $(hostname)"

if [ ! -f "$APISERVER_MANIFEST" ]; then
echo "[ERROR] kube-apiserver manifest not found at $APISERVER_MANIFEST"
exit 1
fi

# Take a one-time backup per run
cp -p "$APISERVER_MANIFEST" "${APISERVER_MANIFEST}${BACKUP_SUFFIX}"
echo "[INFO] Backup created at ${APISERVER_MANIFEST}${BACKUP_SUFFIX}"

# Normalize file by ensuring it ends with a newline
sed -i -e '$a\' "$APISERVER_MANIFEST"

# 1. Remove any existing --service-account-lookup flag (true or false) to avoid duplicates
if grep -q -- "--service-account-lookup=" "$APISERVER_MANIFEST"; then
echo "[INFO] Removing existing --service-account-lookup occurrences"
# Remove the argument token from the command line; keep surrounding content
sed -i 's/--service-account-lookup=[^"'"'"'[:space:]]*//g' "$APISERVER_MANIFEST"
# Clean up possible double spaces left behind
sed -i 's/ \+/ /g' "$APISERVER_MANIFEST"
fi

# 2. Ensure the flag is present with value true.
#
# We handle two common layouts of the kube-apiserver manifest:
# a) args: list form
# b) command: list form with inline args
#
# Prefer adding it to the args list if present; otherwise append to command.

if grep -q '^[[:space:]]*args:[[:space:]]*$' "$APISERVER_MANIFEST"; then
# Check if already present as list item
if grep -q '^[[:space:]]*-[[:space:]]*--service-account-lookup=true[[:space:]]*$' "$APISERVER_MANIFEST"; then
echo "[INFO] --service-account-lookup=true already present in args list"
else
echo "[INFO] Adding --service-account-lookup=true to args list"
# Insert after the args: line, but only once (first occurrence)
awk '
BEGIN {added=0}
/^[[:space:]]*args:[[:space:]]*$/ && !added {
print $0
print " - --service-account-lookup=true"
added=1
next
}
{print $0}
' "$APISERVER_MANIFEST" > "${APISERVER_MANIFEST}.tmp"
mv "${APISERVER_MANIFEST}.tmp" "$APISERVER_MANIFEST"
fi
else
# No args: list. Try to append to command: list
if grep -q '^[[:space:]]*command:[[:space:]]*$' "$APISERVER_MANIFEST"; then
# Check if already present as list item
if grep -q '^[[:space:]]*-[[:space:]]*--service-account-lookup=true[[:space:]]*$' "$APISERVER_MANIFEST"; then
echo "[INFO] --service-account-lookup=true already present in command list"
else
echo "[INFO] Adding --service-account-lookup=true to command list"
awk '
BEGIN {added=0}
/^[[:space:]]*command:[[:space:]]*$/ && !added {
print $0
print " - --service-account-lookup=true"
added=1
next
}
{print $0}
' "$APISERVER_MANIFEST" > "${APISERVER_MANIFEST}.tmp"
mv "${APISERVER_MANIFEST}.tmp" "$APISERVER_MANIFEST"
fi
else
# Fallback: append as a new args section under the kube-apiserver container spec
echo "[INFO] No args: or command: list found; appending minimal args section with --service-account-lookup=true"
awk '
BEGIN {added=0}
/name:[[:space:]]*kube-apiserver/ && !added {
print $0
getline
print $0
print " args:"
print " - --service-account-lookup=true"
added=1
next
}
{print $0}
' "$APISERVER_MANIFEST" > "${APISERVER_MANIFEST}.tmp"
mv "${APISERVER_MANIFEST}.tmp" "$APISERVER_MANIFEST"
fi
fi

echo "[INFO] Manifest updated. kubelet will automatically restart the kube-apiserver static pod."

# VERIFICATION
echo "[INFO] Waiting for kube-apiserver process to reflect new arguments..."
# Wait loop (max 60s) for process args to contain the flag
for i in $(seq 1 30); do
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--service-account-lookup=true"; then
break
fi
sleep 2
done

echo "[INFO] Current kube-apiserver processes:"
/bin/ps -ef | grep kube-apiserver | grep -v grep || true

if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--service-account-lookup=true"; then
echo "[INFO] Verification PASSED: --service-account-lookup=true is set on kube-apiserver"
exit 0
else
echo "[ERROR] Verification FAILED: --service-account-lookup=true not found in kube-apiserver arguments"
echo "[ERROR] Check ${APISERVER_MANIFEST} and kubelet status manually."
exit 1
fi

Additional Reading: