Skip to main content

Ensure Use Service Account Credentials Argument Is Enabled

More Info:

Use individual service account credentials for each controller

Risk Level

High

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. On every control plane node, back up the current manifest:
sudo cp -a /etc/kubernetes/manifests/kube-controller-manager.yaml /etc/kubernetes/manifests/kube-controller-manager.yaml.bak
  1. Edit the controller manager manifest on that control plane node:
sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml
  1. In the spec.containers[0].command (or args) list, add or update the flag so it appears exactly as:
- --use-service-account-credentials=true

If a line with --use-service-account-credentials= already exists, change its value to true instead of adding a duplicate.

  1. Save the file and exit the editor. The kubelet on that control plane node will automatically detect the manifest change and restart the kube-controller-manager static pod; expect a brief controller-manager restart.

  2. After 30–60 seconds, verify the new flag is in effect on that control plane node:

/bin/ps -ef | grep kube-controller-manager | grep -v grep

Confirm the kube-controller-manager process command line includes:

--use-service-account-credentials=true
Using kubectl

kubectl cannot modify the kube-controller-manager static pod manifest or its process flags. This finding must be remediated by editing /etc/kubernetes/manifests/kube-controller-manager.yaml directly on every control plane node; see the Manual Steps section for exact instructions.

Automation
#!/usr/bin/env bash
#
# Remediation: Ensure --use-service-account-credentials=true for kube-controller-manager
# Scope: Run on every control plane node
# Effect: Editing /etc/kubernetes/manifests/kube-controller-manager.yaml will
# trigger an automatic restart of the kube-controller-manager static pod.
#

set -euo pipefail

MANIFEST="/etc/kubernetes/manifests/kube-controller-manager.yaml"
REQUIRED_ARG="--use-service-account-credentials=true"

echo "[INFO] Starting remediation for kube-controller-manager on host: $(hostname)"

if [[ ! -f "${MANIFEST}" ]]; then
echo "[ERROR] Manifest not found: ${MANIFEST}"
exit 1
fi

# Backup manifest once per run (idempotent-safe because we timestamp)
BACKUP="${MANIFEST}.$(date +%Y%m%d%H%M%S).bak"
cp "${MANIFEST}" "${BACKUP}"
echo "[INFO] Backup created at ${BACKUP}"

# Check if argument already present with correct value
if grep -qE '[[:space:]]-'"${REQUIRED_ARG}" "${MANIFEST}"; then
echo "[INFO] Required argument already present: ${REQUIRED_ARG}"
else
echo "[INFO] Updating ${MANIFEST} to ensure ${REQUIRED_ARG} is set"

# If any existing --use-service-account-credentials argument exists, remove it
# to avoid duplicates and ensure the value is true.
if grep -q -- "--use-service-account-credentials=" "${MANIFEST}"; then
# Remove any line containing the flag; safe as long as used only once in args list
tmpfile="$(mktemp)"
sed '/--use-service-account-credentials=/d' "${MANIFEST}" > "${tmpfile}"
mv "${tmpfile}" "${MANIFEST}"
echo "[INFO] Removed existing --use-service-account-credentials lines"
fi

# Insert the required arg in the args list under kube-controller-manager container.
# This assumes a standard kubeadm-style static pod manifest with 'containers:' and 'name: kube-controller-manager'.
tmpfile="$(mktemp)"
awk -v arg="${REQUIRED_ARG}" '
$0 ~ /name:[[:space:]]*kube-controller-manager/ { in_kcm=1 }
in_kcm && $0 ~ /^[[:space:]]*args:[[:space:]]*$/ { in_args=1 }
in_kcm && in_args && $0 !~ /^[[:space:]]*-[[:space:]]/ && $0 !~ /^[[:space:]]*#/ && $0 !~ /^[[:space:]]*$/ { in_args=0 }
{
print $0
if (in_kcm && in_args && $0 ~ /^[[:space:]]*args:[[:space:]]*$/) {
print " - " arg
}
}
' "${MANIFEST}" > "${tmpfile}"

# If awk failed to add the argument (e.g. non-standard manifest), fall back to simple append
if ! grep -qE '[[:space:]]-'"${REQUIRED_ARG}" "${tmpfile}"; then
echo "[WARN] Could not locate standard args section; appending argument under containers section"

awk -v arg="${REQUIRED_ARG}" '
$0 ~ /name:[[:space:]]*kube-controller-manager/ { in_kcm=1 }
in_kcm && $0 ~ /^[[:space:]]*image:[[:space:]]*/ && !printed {
print $0
print " args:"
print " - " arg
printed=1
next
}
{ print $0 }
' "${MANIFEST}" > "${tmpfile}"
fi

mv "${tmpfile}" "${MANIFEST}"
echo "[INFO] Manifest updated. kube-controller-manager static pod will restart automatically."
fi

# Verification: wait for kube-controller-manager process to expose the flag
echo "[INFO] Verifying kube-controller-manager process has ${REQUIRED_ARG} enabled"

# Give kubelet some time to restart the static pod if it changed
sleep 10

if /bin/ps -ef | grep kube-controller-manager | grep -v grep | grep -q -- "${REQUIRED_ARG}"; then
echo "[SUCCESS] kube-controller-manager is running with ${REQUIRED_ARG}"
exit 0
else
echo "[ERROR] kube-controller-manager process is not running with ${REQUIRED_ARG}"
echo "[INFO] Current kube-controller-manager processes:"
/bin/ps -ef | grep kube-controller-manager | grep -v grep || true
exit 2
fi

Usage (run on every control plane node):

chmod +x ./fix-use-service-account-credentials.sh
sudo ./fix-use-service-account-credentials.sh

Additional Reading: