Skip to main content

Ensure Admission Control Plugin NodeRestriction Is Set

More Info:โ€‹

Limit the Node and Pod objects that a kubelet could modify.

Risk Levelโ€‹

Low

Addressโ€‹

Security

Compliance Standardsโ€‹

  • CIS Kubernetes

Triage and Remediationโ€‹

Remediationโ€‹

Manual Steps
  1. Confirm the apiserver manifest exists
    Run on: every control plane node

    ls -l /etc/kubernetes/manifests/kube-apiserver.yaml

    If the file is missing, stop and investigate how the control plane is deployed.

  2. Back up the existing kube-apiserver manifest
    Run on: every control plane node

    sudo cp /etc/kubernetes/manifests/kube-apiserver.yaml \
    /etc/kubernetes/manifests/kube-apiserver.yaml.bak-$(date +%F-%H%M%S)
  3. Edit the kube-apiserver manifest to include NodeRestriction
    Run on: every control plane node
    Open the file:

    sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml

    In the spec.containers[0].command list, locate the existing --enable-admission-plugins= entry, for example:

    - --enable-admission-plugins=NamespaceLifecycle,ServiceAccount

    Modify it so that NodeRestriction is included in the comma-separated list (do not remove existing plugins), for example:

    - --enable-admission-plugins=NamespaceLifecycle,ServiceAccount,NodeRestriction

    If there is no --enable-admission-plugins= line, add one to the command section, preserving other options:

    - --enable-admission-plugins=NodeRestriction

    Save and exit.
    Operational impact: because this is a static pod manifest under /etc/kubernetes/manifests, the kubelet will automatically restart the kube-apiserver pod with the new configuration.

  4. Wait for the kube-apiserver pod to restart and become Ready
    Run on: any machine with kubectl access

    kubectl get pods -n kube-system -l component=kube-apiserver -o wide

    Wait until the kube-apiserver-... pod shows STATUS as Running and READY as 1/1.

  5. Verify the kube-apiserver process includes NodeRestriction in --enable-admission-plugins
    Run on: every control plane node

    /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- '--enable-admission-plugins'

    Confirm the output line for kube-apiserver shows --enable-admission-plugins= with NodeRestriction present in the list, for example:

    --enable-admission-plugins=NamespaceLifecycle,ServiceAccount,NodeRestriction
Using kubectl

kubectl cannot configure admission plugins for the API server or edit /etc/kubernetes/manifests/kube-apiserver.yaml, because this is a host-level static pod manifest on each control plane node. Make the change directly on the control plane nodes as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Automation: Ensure kube-apiserver enables the NodeRestriction admission plugin
# Scope: every control plane node
#
# Run this script as root on each control plane node.
# It is safe to re-run; changes are idempotent.
#
# Operational impact:
# - Editing /etc/kubernetes/manifests/kube-apiserver.yaml will cause the
# kube-apiserver static pod to be restarted by the kubelet.

set -euo pipefail

MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-node-restriction"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"

echo "[*] Ensuring NodeRestriction admission plugin is enabled in ${MANIFEST}"

if [[ $EUID -ne 0 ]]; then
echo "ERROR: This script must be run as root." >&2
exit 1
fi

if [[ ! -f "${MANIFEST}" ]]; then
echo "ERROR: kube-apiserver manifest not found at ${MANIFEST}" >&2
exit 1
fi

mkdir -p "${BACKUP_DIR}"

backup_file="${BACKUP_DIR}/kube-apiserver.yaml.${TIMESTAMP}"
cp -p "${MANIFEST}" "${backup_file}"
echo "[*] Backed up current manifest to ${backup_file}"

# Function to check if NodeRestriction is already present in an --enable-admission-plugins arg line
has_noderestriction_enabled() {
grep -E '^\s*- --enable-admission-plugins=' "${MANIFEST}" | grep -q 'NodeRestriction'
}

# Function to check if there's any --enable-admission-plugins arg line
has_enable_plugins_arg() {
grep -qE '^\s*- --enable-admission-plugins=' "${MANIFEST}"
}

if has_noderestriction_enabled; then
echo "[*] NodeRestriction already present in --enable-admission-plugins; no manifest change needed."
else
echo "[*] Updating ${MANIFEST} to ensure NodeRestriction is enabled..."

tmp_manifest="$(mktemp)"
trap 'rm -f "${tmp_manifest}"' EXIT

if has_enable_plugins_arg; then
# Append NodeRestriction to existing comma-separated list if not present
awk '
/^\s*- --enable-admission-plugins=/ {
line=$0
# remove leading list marker and spaces to inspect value
sub(/^\s*-\s*--enable-admission-plugins=/, "", line)
# if NodeRestriction not already there, append it
if (line !~ /(^|,)NodeRestriction(,|$)/) {
sub(/\r$/, "", line)
$0 = gensub(/(--enable-admission-plugins=)(.*)/,
"\\1" line ",NodeRestriction", 1)
}
}
{ print }
' "${MANIFEST}" > "${tmp_manifest}"
else
# No --enable-admission-plugins line: insert a new one under the "command:" section
awk '
/command:/ && in_container == 0 {
in_container = 1
print
inserted = 0
next
}
in_container == 1 && /^\s*-/ && inserted == 0 {
# Insert the new argument before the first existing command arg
print " - --enable-admission-plugins=NodeRestriction"
inserted = 1
}
{ print }
' "${MANIFEST}" > "${tmp_manifest}"

# Fallback: if we failed to insert (no command: section matched), append at the end
if ! grep -q -- "--enable-admission-plugins=NodeRestriction" "${tmp_manifest}"; then
echo " - --enable-admission-plugins=NodeRestriction" >> "${tmp_manifest}"
fi
fi

mv "${tmp_manifest}" "${MANIFEST}"
sync
echo "[*] Updated ${MANIFEST}. Kubelet will restart the kube-apiserver static pod automatically."
fi

echo "[*] Waiting for kube-apiserver to be running with NodeRestriction enabled..."

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

# Verification: check running kube-apiserver process flags
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--enable-admission-plugins"; then
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- "--enable-admission-plugins" | grep -q "NodeRestriction"; then
echo "[OK] kube-apiserver process has --enable-admission-plugins including NodeRestriction:"
/bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- "--enable-admission-plugins" || true
exit 0
else
echo "[WARN] kube-apiserver is running but --enable-admission-plugins does not include NodeRestriction yet."
echo "Current flag lines:"
/bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- "--enable-admission-plugins" || true
exit 1
fi
else
echo "[WARN] Could not find a running kube-apiserver process with --enable-admission-plugins flag."
/bin/ps -ef | grep kube-apiserver | grep -v grep || true
exit 1
fi

Additional Reading:โ€‹