Skip to main content

Ensure Authorization Mode Argument Is Not Set Always Allow

More Info:

Do not allow all requests. Enable explicit authorization.

Risk Level

Medium

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS AKS
  • CIS Critical Security Controls v8
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. On every worker node, open the kubelet config file and set authorization mode to Webhook:

    sudo sed -i 's/^authorization:.*$/authorization:\n mode: Webhook/' /var/lib/kubelet/config.yaml || {
    echo "authorization:" | sudo tee -a /var/lib/kubelet/config.yaml
    echo " mode: Webhook" | sudo tee -a /var/lib/kubelet/config.yaml
    }
  2. If the kubelet is started with flags instead of (or in addition to) the config file, edit the systemd drop-in on every worker node:

    sudo nano /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

    In the Environment="KUBELET_AUTHZ_ARGS=..." line, ensure it contains:

    --authorization-mode=Webhook

    and remove any --authorization-mode=AlwaysAllow if present. Save and exit.

  3. Reload systemd and restart kubelet on every worker node so changes take effect:

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
  4. Verify on every worker node that kubelet is no longer using AlwaysAllow and is using Webhook:

    /bin/ps -fC kubelet

    Confirm the output does not contain --authorization-mode=AlwaysAllow and shows --authorization-mode=Webhook or that the process is using /var/lib/kubelet/config.yaml with authorization: mode: Webhook.

Using kubectl

kubectl cannot change kubelet authorization settings because they are controlled by host-level configuration on each worker node (for example /var/lib/kubelet/config.yaml or the systemd unit). Make the changes directly on the nodes as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
# Purpose: Ensure kubelet authorization mode is set to Webhook on every worker node.
# Scope: Run on EACH worker node as root.
# Idempotent: Safe to re-run.

set -euo pipefail

KUBELET_CONFIG="/var/lib/kubelet/config.yaml"
SYSTEMD_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"

echo "[INFO] Updating kubelet authorization mode on worker node: $(hostname)"

if [[ ! -f "${KUBELET_CONFIG}" ]]; then
echo "[ERROR] Kubelet config file ${KUBELET_CONFIG} not found. Aborting."
exit 1
fi

# Backup once
if [[ ! -f "${KUBELET_CONFIG}.bak.cisaks-3.2.2" ]]; then
cp -p "${KUBELET_CONFIG}" "${KUBELET_CONFIG}.bak.cisaks-3.2.2"
echo "[INFO] Backup created at ${KUBELET_CONFIG}.bak.cisaks-3.2.2"
fi

# Ensure 'authorization:' block exists and set mode: Webhook
# This uses a conservative edit: remove any existing 'authorization:' block
# and append a clean one at the end.

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

in_auth_block=0
while IFS='' read -r line; do
# Detect start of authorization block
if [[ "${line}" =~ ^authorization:([[:space:]]*)$ ]]; then
in_auth_block=1
continue
fi
# If inside authorization block, skip lines indented under it
if [[ ${in_auth_block} -eq 1 ]]; then
if [[ "${line}" =~ ^[[:space:]] ]]; then
continue
else
in_auth_block=0
fi
fi
echo "${line}" >> "${tmp_cfg}"
done < "${KUBELET_CONFIG}"

# Append correct authorization block (2-space indent)
cat >> "${tmp_cfg}" <<'EOF'
authorization:
mode: Webhook
EOF

# Only replace if changed
if ! diff -q "${KUBELET_CONFIG}" "${tmp_cfg}" >/dev/null 2>&1; then
cp "${tmp_cfg}" "${KUBELET_CONFIG}"
echo "[INFO] Updated ${KUBELET_CONFIG} with authorization.mode=Webhook"
else
echo "[INFO] ${KUBELET_CONFIG} already has authorization.mode=Webhook"
fi

# Ensure systemd drop-in does NOT force an AlwaysAllow mode; set to Webhook if present.
if [[ -f "${SYSTEMD_DROPIN}" ]]; then
if ! grep -q 'KUBELET_AUTHZ_ARGS' "${SYSTEMD_DROPIN}"; then
# Add variable with Webhook
cat >> "${SYSTEMD_DROPIN}" <<'EOF'

Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook"
EOF
echo "[INFO] Added KUBELET_AUTHZ_ARGS to ${SYSTEMD_DROPIN}"
else
# Replace any existing authorization-mode value with Webhook
sed -i \
-e 's/--authorization-mode=[^" ]*/--authorization-mode=Webhook/g' \
"${SYSTEMD_DROPIN}"
echo "[INFO] Ensured KUBELET_AUTHZ_ARGS uses --authorization-mode=Webhook in ${SYSTEMD_DROPIN}"
fi
else
echo "[WARN] ${SYSTEMD_DROPIN} not found; assuming kubelet uses only config file."
fi

echo "[INFO] Reloading systemd and restarting kubelet (this will restart the kubelet process)."
systemctl daemon-reload
systemctl restart kubelet.service

sleep 5

echo "[INFO] Verifying kubelet authorization mode (via process flags and config)..."

/bin/ps -fC kubelet || {
echo "[ERROR] kubelet process not found after restart."
exit 1
}

# Check process args for any AlwaysAllow
if /bin/ps -fC kubelet | grep -q -- '--authorization-mode=AlwaysAllow'; then
echo "[ERROR] kubelet still running with --authorization-mode=AlwaysAllow in process flags."
exit 1
fi

# Verify config file contains mode: Webhook
if ! grep -qE '^authorization:[[:space:]]*$' "${KUBELET_CONFIG}" || \
! grep -qE '^[[:space:]]+mode:[[:space:]]*Webhook[[:space:]]*$' "${KUBELET_CONFIG}"; then
echo "[ERROR] ${KUBELET_CONFIG} does not show authorization.mode=Webhook."
exit 1
fi

echo "[INFO] Verification complete: kubelet authorization mode is not AlwaysAllow and is configured as Webhook."

Additional Reading: