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 Critical Security Controls v8
  • CIS GKE
  • 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, SSH in and confirm how kubelet is started and where its config lives:

    ps -ef | grep kubelet

    If you see a --config=/var/lib/kubelet/config.yaml (or similar) argument, proceed with Method 1 below. If you instead see explicit flags like --authorization-mode=AlwaysAllow, use Method 2.

  2. Method 1 – kubelet config file (/var/lib/kubelet/config.yaml):
    a. Back up and edit the config:

    sudo cp /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak
    sudo vi /var/lib/kubelet/config.yaml

    b. In the YAML, ensure these sections exist and are set correctly (add or adjust as needed):

    authentication:
    webhook:
    enabled: true
    authorization:
    mode: Webhook

    c. Save the file.

  3. Method 2 – kubelet executable arguments (systemd):
    a. Back up and edit the kubelet systemd drop‑in:

    sudo cp /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf.bak
    sudo vi /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf

    b. In the KUBELET_ARGS (or equivalent) line, remove any --authorization-mode=AlwaysAllow and ensure these flags are present:

    --authentication-token-webhook \
    --authorization-mode=Webhook

    c. Save the file.

  4. On every worker node, reload systemd and restart kubelet (both methods):

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
    sudo systemctl status kubelet -l

    Ensure the service is active (running) and no errors are reported related to the new flags/config.

  5. Verification on every worker node (derived from the audit command):

    /bin/ps -fC kubelet

    Confirm that:

    • There is no --authorization-mode=AlwaysAllow in the kubelet command line, and
    • Either the kubelet is using /var/lib/kubelet/config.yaml where authorization.mode: Webhook is set, or the process flags include --authorization-mode=Webhook and --authentication-token-webhook.
Using kubectl

kubectl cannot modify kubelet host-level configuration such as /var/lib/kubelet/config.yaml or the kubelet systemd unit and flags on worker nodes. To remediate this finding, you must make the changes directly on each node’s OS (kubelet config file or systemd unit) as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Fix CIS GKE 3.2.2 on every worker node:
# Ensure kubelet does NOT use AlwaysAllow and uses Webhook auth/authz instead.
#
# Run this on EACH WORKER NODE over SSH as root or with sudo.
# Safe to re-run: only adds/updates required settings.

set -euo pipefail

echo "[INFO] Detecting kubelet process and configuration method..."

# Locate kubelet process
if ! ps -fC kubelet >/dev/null 2>&1; then
echo "[ERROR] kubelet process not found on this node. Nothing to fix."
exit 1
fi

KUBELET_CMDLINE="$(ps -o args= -C kubelet | head -n1 || true)"

if [[ -z "${KUBELET_CMDLINE}" ]]; then
echo "[ERROR] Unable to read kubelet command line."
exit 1
fi

echo "[INFO] kubelet command line: ${KUBELET_CMDLINE}"

# Determine if kubelet uses a config file (Method 1) or only flags (Method 2)
CONFIG_FILE=""
if [[ "${KUBELET_CMDLINE}" =~ --config[=[:space:]]([^[:space:]]+) ]]; then
CONFIG_FILE="${BASH_REMATCH[1]}"
fi

SYSTEMD_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubelet-args.conf"
USE_METHOD=2

if [[ -n "${CONFIG_FILE}" ]]; then
USE_METHOD=1
echo "[INFO] Detected kubelet config file: ${CONFIG_FILE}"
else
echo "[INFO] No --config flag detected, will use kubelet executable arguments (Method 2)."
fi

backup_file() {
local f="$1"
if [[ -f "${f}" ]]; then
local ts
ts="$(date +%Y%m%d%H%M%S)"
local backup="${f}.cisgke-3.2.2.bak.${ts}"
cp -p "${f}" "${backup}"
echo "[INFO] Backup created: ${backup}"
fi
}

ensure_systemd_reload_needed=0

#######################################
# Method 1: kubelet config file
#######################################
if [[ "${USE_METHOD}" -eq 1 ]]; then
if [[ ! -f "${CONFIG_FILE}" ]]; then
echo "[ERROR] Kubelet config file '${CONFIG_FILE}' not found. Cannot apply Method 1."
echo "[INFO] Falling back to Method 2 (kubelet flags via systemd), if available."
USE_METHOD=2
else
backup_file "${CONFIG_FILE}"

echo "[INFO] Ensuring Webhook authentication and authorization in kubelet config file..."

# If file appears JSON-like (starts with {), operate with simple JSON-aware edits.
# If not JSON, we still attempt structured insertion using jq if available.
if command -v jq >/dev/null 2>&1; then
TMP="$(mktemp)"
trap 'rm -f "${TMP}"' EXIT

# Convert to canonical JSON via jq; if fails, treat as plain text.
if jq . "${CONFIG_FILE}" >/dev/null 2>&1; then
jq '
.authentication.webhook.enabled = true
| .authorization.mode = "Webhook"
' "${CONFIG_FILE}" > "${TMP}"
mv "${TMP}" "${CONFIG_FILE}"
chmod 600 "${CONFIG_FILE}" || true
echo "[INFO] Updated kubelet config JSON using jq."
else
echo "[WARN] kubelet config is not valid JSON; please update manually per benchmark."
echo " Set: \"authentication\": { \"webhook\": { \"enabled\": true } }"
echo " and: \"authorization\": { \"mode\": \"Webhook\" }"
fi
else
echo "[WARN] jq not installed; cannot safely edit JSON kubelet config automatically."
echo " Please manually ensure:"
echo " \"authentication\": { \"webhook\": { \"enabled\": true } }"
echo " \"authorization\": { \"mode\": \"Webhook\" }"
fi

ensure_systemd_reload_needed=1
fi
fi

#######################################
# Method 2: kubelet executable args
#######################################
if [[ "${USE_METHOD}" -eq 2 ]]; then
if [[ ! -f "${SYSTEMD_DROPIN}" ]]; then
echo "[ERROR] Expected systemd drop-in '${SYSTEMD_DROPIN}' not found."
echo "[ERROR] Cannot apply Method 2 automatically on this OS layout."
echo " Update your kubelet service configuration to include:"
echo " --authentication-token-webhook"
echo " --authorization-mode=Webhook"
exit 1
fi

backup_file "${SYSTEMD_DROPIN}"

echo "[INFO] Updating kubelet systemd drop-in: ${SYSTEMD_DROPIN}"

# Ensure file has a KUBELET_ARGS line; if not, append one.
if ! grep -q 'KUBELET_ARGS' "${SYSTEMD_DROPIN}"; then
cat <<'EOF' >> "${SYSTEMD_DROPIN}"

Environment="KUBELET_ARGS=--authentication-token-webhook --authorization-mode=Webhook"
EOF
else
# Ensure --authentication-token-webhook present
if ! grep -q -- '--authentication-token-webhook' "${SYSTEMD_DROPIN}"; then
sed -i 's/\(KUBELET_ARGS=.*\)"/\1 --authentication-token-webhook"/' "${SYSTEMD_DROPIN}" || true
fi
# Ensure --authorization-mode is set to Webhook (replace AlwaysAllow or others)
if grep -q -- '--authorization-mode=' "${SYSTEMD_DROPIN}"; then
sed -i 's/--authorization-mode=[^" ]*/--authorization-mode=Webhook/g' "${SYSTEMD_DROPIN}" || true
else
sed -i 's/\(KUBELET_ARGS=.*\)"/\1 --authorization-mode=Webhook"/' "${SYSTEMD_DROPIN}" || true
fi
fi

ensure_systemd_reload_needed=1
fi

#######################################
# Restart kubelet (operational impact)
#######################################
if [[ "${ensure_systemd_reload_needed}" -eq 1 ]]; then
echo "[INFO] Reloading systemd and restarting kubelet (this will briefly disrupt workloads on this node)..."
systemctl daemon-reload
systemctl restart kubelet.service

echo "[INFO] kubelet service status:"
systemctl status kubelet -l --no-pager || true
fi

#######################################
# Verification (adapted from audit)
#######################################
echo "[INFO] Verifying that kubelet is NOT using AlwaysAllow and is using Webhook authorization..."

KUBELET_CMDLINE_NEW="$(ps -o args= -C kubelet | head -n1 || true)"
echo "[INFO] Current kubelet command line: ${KUBELET_CMDLINE_NEW}"

if echo "${KUBELET_CMDLINE_NEW}" | grep -q -- '--authorization-mode=AlwaysAllow'; then
echo "[FAIL] kubelet is still configured with --authorization-mode=AlwaysAllow"
exit 1
fi

if echo "${KUBELET_CMDLINE_NEW}" | grep -q -- '--authorization-mode=Webhook'; then
echo "[OK] kubelet authorization-mode is set to Webhook via executable arguments."
fi

if [[ -n "${CONFIG_FILE:-}" && -f "${CONFIG_FILE}" ]]; then
echo "[INFO] Checking kubelet config file for Webhook settings: ${CONFIG_FILE}"
grep -E '"authorization"[[:space:]]*:' -n "${CONFIG_FILE}" || true
grep -E '"mode"[[:space:]]*:[[:space:]]*"Webhook"' -n "${CONFIG_FILE}" || true
grep -E '"authentication"[[:space:]]*:' -n "${CONFIG_FILE}" || true
grep -E '"webhook"[[:space:]]*:' -n "${CONFIG_FILE}" || true
grep -E '"enabled"[[:space:]]*:[[:space:]]*true' -n "${CONFIG_FILE}" || true
fi

/bin/ps -fC kubelet || true

echo "[INFO] CIS GKE 3.2.2 remediation script completed on this node."

Additional Reading: