Kubelet Authorization Mode Not Set To AlwaysAllow
More Info:
The kubelet --authorization-mode argument must not be set to AlwaysAllow. AlwaysAllow authorizes every request to the kubelet, bypassing access controls on the node.
Risk Level
Critical
Address
Security
Compliance Standards
- CIS OKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every worker node, inspect the current kubelet process to confirm it is using
AlwaysAllow:/bin/ps -fC kubeletLook for
--authorization-mode=AlwaysAllowor a missing--authorization-modeflag (which may default insecurely depending on your setup). -
On every worker node, edit the kubelet systemd drop-in to set webhook authorization:
sudo vi /etc/systemd/system/kubelet.service.d/00-default.confIn the
ExecStart=line, ensure--authorization-mode=Webhookis present and noAlwaysAllowvalue remains. For example:ExecStart=/usr/bin/kubelet \--authorization-mode=Webhook \...Save and exit.
-
If your kubelet also uses a config file (
/etc/kubernetes/kubelet-config.json), update itsauthorizationblock to avoidAlwaysAllow(if present):sudo vi /etc/kubernetes/kubelet-config.jsonEnsure it is set similar to:
{"authorization": {"mode": "Webhook"}}Save and exit.
-
On every worker node, reload systemd and restart kubelet for the changes to take effect:
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
On every worker node, confirm kubelet started cleanly:
sudo systemctl status kubelet -l -
Verify the remediation on every worker node by confirming
AlwaysAllowis not present andWebhookis used:/bin/ps -fC kubeletEnsure the output shows
--authorization-mode=Webhookand does not show--authorization-mode=AlwaysAllow.
Using kubectl
kubectl cannot modify kubelet process flags or host-level config files such as /etc/kubernetes/kubelet-config.json or /etc/systemd/system/kubelet.service.d/00-default.conf; those must be changed directly on every worker node. Refer to the Manual Steps section for the exact on-node configuration and restart procedure to set --authorization-mode=Webhook and remove AlwaysAllow.
Automation
#!/usr/bin/env bash
#
# Automates CISOKE 3.2.2 remediation:
# Ensure kubelet --authorization-mode is not set to AlwaysAllow
# and is set to Webhook in systemd drop-in, then restart kubelet.
#
# Run this on every worker node as root.
# Safe to re-run (idempotent).
set -euo pipefail
KUBELET_DROPIN_DIR="/etc/systemd/system/kubelet.service.d"
KUBELET_DROPIN_FILE="${KUBELET_DROPIN_DIR}/00-default.conf"
echo "=== CISOKE 3.2.2: Fixing kubelet authorization-mode on worker node $(hostname) ==="
if [[ $EUID -ne 0 ]]; then
echo "ERROR: This script must be run as root." >&2
exit 1
fi
if ! command -v systemctl >/dev/null 2>&1; then
echo "ERROR: systemd/systemctl not found; cannot manage kubelet service on this node." >&2
exit 1
fi
if ! systemctl list-unit-files | grep -q '^kubelet\.service'; then
echo "INFO: kubelet.service not found via systemd; nothing to do on this node."
exit 0
fi
# Ensure drop-in directory exists
mkdir -p "${KUBELET_DROPIN_DIR}"
if [[ ! -f "${KUBELET_DROPIN_FILE}" ]]; then
echo "INFO: ${KUBELET_DROPIN_FILE} not found, creating new drop-in."
cat > "${KUBELET_DROPIN_FILE}.tmp" <<'EOF'
[Service]
# CISOKE 3.2.2: Ensure kubelet --authorization-mode is not set to AlwaysAllow
# and is explicitly set to Webhook.
Environment="KUBELET_AUTHORIZATION_ARGS=--authorization-mode=Webhook"
EOF
mv "${KUBELET_DROPIN_FILE}.tmp" "${KUBELET_DROPIN_FILE}"
else
echo "INFO: Updating ${KUBELET_DROPIN_FILE} to enforce --authorization-mode=Webhook"
# Backup original (once)
if [[ ! -f "${KUBELET_DROPIN_FILE}.bak" ]]; then
cp "${KUBELET_DROPIN_FILE}" "${KUBELET_DROPIN_FILE}.bak"
fi
tmp="${KUBELET_DROPIN_FILE}.tmp"
> "${tmp}"
in_service_section=0
auth_env_found=0
while IFS= read -r line; do
case "${line}" in
"[Service]")
in_service_section=1
echo "${line}" >> "${tmp}"
;;
\[*)
# another section
in_service_section=0
echo "${line}" >> "${tmp}"
;;
Environment*=*authorization-mode*=*)
# Normalize any existing authorization-mode definition
echo 'Environment="KUBELET_AUTHORIZATION_ARGS=--authorization-mode=Webhook"' >> "${tmp}"
auth_env_found=1
;;
*)
echo "${line}" >> "${tmp}"
;;
esac
done < "${KUBELET_DROPIN_FILE}"
# If no Environment line for authorization-mode existed, add one in [Service]
if [[ ${auth_env_found} -eq 0 ]]; then
# If there was no [Service] section at all, append one
if ! grep -q '^\[Service\]' "${tmp}"; then
{
echo
echo "[Service]"
} >> "${tmp}"
fi
echo 'Environment="KUBELET_AUTHORIZATION_ARGS=--authorization-mode=Webhook"' >> "${tmp}"
fi
mv "${tmp}" "${KUBELET_DROPIN_FILE}"
fi
echo "INFO: Reloading systemd and restarting kubelet (this will restart kubelet and may briefly affect workloads on this node)."
systemctl daemon-reload
systemctl restart kubelet.service
echo "INFO: kubelet status:"
systemctl status kubelet -l --no-pager || true
echo "INFO: Verifying kubelet process flags (CIS audit equivalent)..."
/bin/ps -fC kubelet || {
echo "ERROR: kubelet process not found after restart." >&2
exit 1
}
# Show effective authorization-mode argument
auth_mode=$(/bin/ps -o args= -C kubelet | tr ' ' '\n' | grep -E '^--authorization-mode=' || true)
if [[ -z "${auth_mode}" ]]; then
echo "WARNING: kubelet args do not explicitly show --authorization-mode flag in process list."
echo " Ensure your kubelet startup command consumes KUBELET_AUTHORIZATION_ARGS from the systemd drop-in."
else
echo "INFO: kubelet authorization-mode flag: ${auth_mode}"
if echo "${auth_mode}" | grep -q 'AlwaysAllow'; then
echo "ERROR: kubelet is still using --authorization-mode=AlwaysAllow. Manual investigation required." >&2
exit 1
fi
if ! echo "${auth_mode}" | grep -q 'Webhook'; then
echo "ERROR: kubelet --authorization-mode is not set to Webhook. Manual investigation required." >&2
exit 1
fi
fi
echo "=== Remediation and verification completed on $(hostname) ==="