Skip to main content

API Server Should Enable The NodeRestriction Admission

More Info:

Verifies that the NodeRestriction admission plugin is enabled so kubelets can only modify their own node and pod objects, limiting a compromised nodes reach.

Risk Level

High

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. On every control plane node, back up the API server static pod manifest:
sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml \
/etc/kubernetes/manifests/kube-apiserver.yaml.backup.$(date +%F-%H%M%S)
  1. On every control plane node, open the manifest for editing:
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
  1. In the container command section, locate the --enable-admission-plugins argument.
    • If it exists, ensure NodeRestriction is listed (comma‑separated), for example:
- --enable-admission-plugins=NamespaceLifecycle,ServiceAccount,NodeRestriction,ResourceQuota
  • If it does not exist, add a new line in the command list, e.g.:
- --enable-admission-plugins=NodeRestriction
  1. Save the file and exit the editor. The kubelet will automatically restart the kube-apiserver static pod because the manifest under /etc/kubernetes/manifests changed, which will briefly restart the API server on that node.

  2. Wait for the API server pod to come back to Running on the control plane node (you can monitor with):

sudo crictl ps | grep kube-apiserver
  1. Verify on every control plane node that the kube-apiserver process includes NodeRestriction in --enable-admission-plugins:
/bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- '--enable-admission-plugins' | grep NodeRestriction
Using kubectl

kubectl cannot configure API server admission plugins or edit the static pod manifest at /etc/kubernetes/manifests/kube-apiserver.yaml on control plane nodes. To enable the NodeRestriction admission plugin and remediate this finding, follow the guidance in the Manual Steps section on each control plane node.

Automation
#!/usr/bin/env bash
#
# Automation: Ensure kube-apiserver enables the NodeRestriction admission plugin
# Target: 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_DIR="/etc/kubernetes/manifests/backup-$(date -u +%Y%m%dT%H%M%SZ)"

echo "[*] Checking for kube-apiserver manifest at ${APISERVER_MANIFEST}"
if [[ ! -f "${APISERVER_MANIFEST}" ]]; then
echo "ERROR: ${APISERVER_MANIFEST} not found on this node. Is this a control plane node?"
exit 1
fi

mkdir -p "${BACKUP_DIR}"

echo "[*] Backing up current manifest to ${BACKUP_DIR}"
cp -p "${APISERVER_MANIFEST}" "${BACKUP_DIR}/kube-apiserver.yaml"

echo "[*] Ensuring --enable-admission-plugins includes NodeRestriction"

# Case 1: --enable-admission-plugins already present
if grep -q -- '--enable-admission-plugins=' "${APISERVER_MANIFEST}"; then
# If NodeRestriction is already in the list, no change needed
if grep -q -- '--enable-admission-plugins=.*NodeRestriction' "${APISERVER_MANIFEST}"; then
echo "[*] NodeRestriction already enabled in --enable-admission-plugins; no manifest change required."
else
echo "[*] Adding NodeRestriction to existing --enable-admission-plugins list"
# Append NodeRestriction to the list, preserving existing plugins
# This assumes standard YAML args list where the flag is in one line
tmpfile="$(mktemp)"
sed -E 's/(--enable-admission-plugins=)([^"]*)/\1\2,NodeRestriction/' \
"${APISERVER_MANIFEST}" > "${tmpfile}"
mv "${tmpfile}" "${APISERVER_MANIFEST}"
echo "[*] Updated --enable-admission-plugins to include NodeRestriction"
fi
else
echo "[*] --enable-admission-plugins not present; adding with NodeRestriction"
# Insert a new args line under the kube-apiserver container spec
# This will be idempotent because we guard on flag absence above.
tmpfile="$(mktemp)"
awk '
/- name: kube-apiserver/ { in_container=1 }
in_container && /args:/ && !added {
print $0
print " - --enable-admission-plugins=NodeRestriction"
added=1
next
}
{ print $0 }
' "${APISERVER_MANIFEST}" > "${tmpfile}"

mv "${tmpfile}" "${APISERVER_MANIFEST}"
echo "[*] Added --enable-admission-plugins=NodeRestriction to kube-apiserver args"
fi

echo "[*] Waiting for kube-apiserver static pod to restart (this may take up to a minute)..."
sleep 30

echo "[*] Verifying that kube-apiserver process has NodeRestriction enabled"
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- '--enable-admission-plugins=.*NodeRestriction'; then
echo "[OK] kube-apiserver is running with --enable-admission-plugins including NodeRestriction"
exit 0
fi

echo "[WARN] kube-apiserver process does not yet show NodeRestriction in --enable-admission-plugins."
echo " Re-check with:"
echo " /bin/ps -ef | grep kube-apiserver | grep -v grep"
exit 1

Usage

Run this script on every control plane node as a user with permission to modify /etc/kubernetes/manifests/kube-apiserver.yaml:

sudo bash ./enable_noderestriction.sh