Kubelet Authorization Mode Not Set To AlwaysAllow
More Info:โ
The kubelet --authorization-mode must not be AlwaysAllow, which would authorize every request. Use Webhook so requests are properly authorized.
Risk Levelโ
Critical
Addressโ
Security
Compliance Standardsโ
- CIS AKS
Triage and Remediationโ
- Remediation
Remediationโ
Manual Steps
- On every worker node, back up the existing kubelet config file:
sudo cp -p /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak.$(date +%F-%H%M%S)
- On every worker node, edit
/var/lib/kubelet/config.yamland set the authorization mode toWebhook(create the block if it does not exist). For example:
sudo sed -i 's/^authorization:.*//g' /var/lib/kubelet/config.yaml
sudo sed -i '/^$/d' /var/lib/kubelet/config.yaml
printf '\nauthorization:\n mode: Webhook\n' | sudo tee -a /var/lib/kubelet/config.yaml
(If your file already has an authorization: block, instead open it in an editor and change only the mode: line to mode: Webhook.)
- If the worker node also sets kubelet flags via systemd, ensure
--authorization-modeis not set toAlwaysAllow. On each worker node:
sudo sed -i 's/--authorization-mode=AlwaysAllow//g' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
If you need to explicitly set Webhook via flags, append:
sudo sed -i 's#KUBELET_AUTHZ_ARGS="#KUBELET_AUTHZ_ARGS="--authorization-mode=Webhook #g' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
- On every worker node, reload systemd and restart kubelet (this restarts the kubelet process and may briefly impact node readiness):
sudo systemctl daemon-reload
sudo systemctl restart kubelet.service
- On every worker node, verify kubelet is no longer using
AlwaysAllow:
/bin/ps -fC kubelet
Confirm the kubelet command line does not contain --authorization-mode=AlwaysAllow and, if present, uses --authorization-mode=Webhook.
Using kubectl
kubectl cannot modify kubelet host-level configuration such as /var/lib/kubelet/config.yaml or systemd units on worker nodes. Make the change directly on each worker node as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Fix CIS AKS 3.2.2: ensure kubelet authorization.mode is Webhook
# Target: every worker node
# Run on: each worker node (as root)
#
# Idempotent: safe to re-run.
set -euo pipefail
KUBELET_CONFIG="/var/lib/kubelet/config.yaml"
SYSTEMD_UNIT="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"
echo "[INFO] Starting kubelet authorization-mode remediation"
############################################
# 1. Ensure kubelet config.yaml uses Webhook
############################################
if [ -f "${KUBELET_CONFIG}" ]; then
echo "[INFO] Detected kubelet config file at ${KUBELET_CONFIG}"
# Ensure 'authorization:' block exists
if ! grep -qE '^[[:space:]]*authorization:' "${KUBELET_CONFIG}"; then
echo "[INFO] Adding authorization block to ${KUBELET_CONFIG}"
cat <<'EOF' >> "${KUBELET_CONFIG}"
authorization:
mode: Webhook
EOF
else
echo "[INFO] Updating authorization.mode to Webhook in ${KUBELET_CONFIG}"
# If 'mode:' exists under authorization, change to Webhook; otherwise add it.
# This uses a small awk program to be robust and idempotent.
tmpfile="$(mktemp)"
awk '
BEGIN {
in_auth = 0
}
/^[[:space:]]*authorization:[[:space:]]*$/ {
in_auth = 1
print
next
}
/^[^[:space:]]/ {
# new top-level section
if (in_auth == 1) {
# we just left authorization block without seeing mode, so add it
print " mode: Webhook"
}
in_auth = 0
print
next
}
{
if (in_auth == 1 && $1 == "mode:" ) {
# replace mode line
sub(/mode:[[:space:]]*.*/, "mode: Webhook")
print
} else {
print
}
}
END {
if (in_auth == 1) {
# file ended while still in authorization block; ensure mode present
print " mode: Webhook"
}
}
' "${KUBELET_CONFIG}" > "${tmpfile}"
cp "${tmpfile}" "${KUBELET_CONFIG}"
rm -f "${tmpfile}"
fi
else
echo "[WARN] ${KUBELET_CONFIG} not found; skipping config.yaml-based change"
fi
###################################################
# 2. Ensure kubelet systemd args do not force AlwaysAllow
# and prefer Webhook if using CLI flags
###################################################
if [ -f "${SYSTEMD_UNIT}" ]; then
echo "[INFO] Detected kubelet systemd drop-in at ${SYSTEMD_UNIT}"
# Ensure KUBELET_AUTHZ_ARGS line exists
if ! grep -q 'KUBELET_AUTHZ_ARGS' "${SYSTEMD_UNIT}"; then
echo "[INFO] Adding KUBELET_AUTHZ_ARGS with --authorization-mode=Webhook"
cat <<'EOF' >> "${SYSTEMD_UNIT}"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook"
EOF
else
echo "[INFO] Updating KUBELET_AUTHZ_ARGS to use --authorization-mode=Webhook"
# Remove any existing --authorization-mode argument
sed -i \
-e 's/\(--authorization-mode[= ][^" ]*\)//g' \
"${SYSTEMD_UNIT}"
# Normalize whitespace inside the line
sed -i 's/Environment="KUBELET_AUTHZ_ARGS=\s*/Environment="KUBELET_AUTHZ_ARGS=/g' "${SYSTEMD_UNIT}"
# Ensure Webhook is present
if grep -q 'KUBELET_AUTHZ_ARGS=.*--authorization-mode=Webhook' "${SYSTEMD_UNIT}"; then
echo "[INFO] KUBELET_AUTHZ_ARGS already contains --authorization-mode=Webhook"
else
# Append to existing value, taking care of quotes
sed -i 's/^\(Environment="KUBELET_AUTHZ_ARGS=.*\)"/\1 --authorization-mode=Webhook"/' "${SYSTEMD_UNIT}"
fi
fi
else
echo "[WARN] ${SYSTEMD_UNIT} not found; skipping CLI-flag-based change"
fi
#####################################
# 3. Reload systemd and restart kubelet
#####################################
echo "[INFO] Reloading systemd and restarting kubelet (this will restart kubelet)"
systemctl daemon-reload
systemctl restart kubelet.service
#####################################
# 4. Verification (CIS audit adaptation)
#####################################
echo "[INFO] Verifying kubelet authorization-mode (via process flags and config.yaml)"
# Original audit style: process listing
/bin/ps -fC kubelet || {
echo "[ERROR] kubelet process not found after restart"
exit 1
}
# Show process args for manual confirmation
echo "[INFO] kubelet process arguments:"
/bin/ps -o pid,cmd -C kubelet
# Check for AlwaysAllow in process args
if /bin/ps -o cmd -C kubelet | grep -q -- '--authorization-mode=AlwaysAllow'; then
echo "[ERROR] kubelet still running with --authorization-mode=AlwaysAllow"
exit 1
fi
# If using config file, verify mode: Webhook
if [ -f "${KUBELET_CONFIG}" ]; then
if grep -qE '^[[:space:]]*authorization:[[:space:]]*$' "${KUBELET_CONFIG}" && \
awk '
/^[[:space:]]*authorization:[[:space:]]*$/ { in_auth=1; next }
/^[^[:space:]]/ { in_auth=0 }
in_auth && $1=="mode:" { print $2 }
' "${KUBELET_CONFIG}" | grep -q '^Webhook$'; then
echo "[INFO] Verified ${KUBELET_CONFIG} has authorization.mode: Webhook"
else
echo "[ERROR] ${KUBELET_CONFIG} does not have authorization.mode: Webhook"
exit 1
fi
fi
echo "[INFO] Remediation complete on this node"