Skip to main content

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

Manual Steps
  1. On every worker node, inspect the current kubelet process to confirm it is using AlwaysAllow:

    /bin/ps -fC kubelet

    Look for --authorization-mode=AlwaysAllow or a missing --authorization-mode flag (which may default insecurely depending on your setup).

  2. On every worker node, edit the kubelet systemd drop-in to set webhook authorization:

    sudo vi /etc/systemd/system/kubelet.service.d/00-default.conf

    In the ExecStart= line, ensure --authorization-mode=Webhook is present and no AlwaysAllow value remains. For example:

    ExecStart=/usr/bin/kubelet \
    --authorization-mode=Webhook \
    ...

    Save and exit.

  3. If your kubelet also uses a config file (/etc/kubernetes/kubelet-config.json), update its authorization block to avoid AlwaysAllow (if present):

    sudo vi /etc/kubernetes/kubelet-config.json

    Ensure it is set similar to:

    {
    "authorization": {
    "mode": "Webhook"
    }
    }

    Save and exit.

  4. On every worker node, reload systemd and restart kubelet for the changes to take effect:

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
  5. On every worker node, confirm kubelet started cleanly:

    sudo systemctl status kubelet -l
  6. Verify the remediation on every worker node by confirming AlwaysAllow is not present and Webhook is used:

    /bin/ps -fC kubelet

    Ensure the output shows --authorization-mode=Webhook and 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) ==="