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
Remediation
Manual Steps
- 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
- In the
spec.containers[0].commandlist, 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
-
If you prefer to rely on the default behavior instead of setting it explicitly, remove any existing
--service-account-lookup=entry from thecommandlist and leave it absent (do not add a replacement). -
Save the file and exit the editor; the kubelet will detect the manifest change and automatically restart the
kube-apiserverstatic pod. Allow a few moments for it to restart. -
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
- In the output, confirm that either:
--service-account-lookup=trueis 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