Skip to main content

The --authorization-mode Argument Is Not Set To AlwaysAllow

More Info:​

Setting the kubelet authorization mode to AlwaysAllow permits every authenticated request without checking permissions. Use Webhook mode so requests are authorized against the API server.

Risk Level​

Critical

Address​

Security

Compliance Standards​

  • CIS EKS

Triage and Remediation​

Remediation​

Manual Steps
  1. On every worker node, confirm how kubelet is configured and where its config file is:

    ps -ef | grep kubelet
    • If you see --config=/var/lib/kubelet/config.yaml (or another path), note that path.
    • If you instead see flags like --authorization-mode=AlwaysAllow directly, follow step 3 (flag-based config).
  2. If using the kubelet config file (e.g. /var/lib/kubelet/config.yaml), edit it to enable webhook authn/z (YAML form of the benchmark’s JSON example):

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

    Ensure these sections exist and are set as follows (add or adjust as needed):

    authentication:
    webhook:
    enabled: true

    authorization:
    mode: Webhook

    Save the file.

  3. If using executable arguments and you find --authorization-mode=AlwaysAllow or missing webhook options in the systemd drop-in, edit the kubelet args file:

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

    In the line defining extra args (for example KUBELET_ARGS= or KUBELET_CONFIG_ARGS=), remove any --authorization-mode=AlwaysAllow and ensure the following flags are present:

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

    Save the file.

  4. Reload systemd configuration and restart kubelet (this will restart the kubelet on this worker node):

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
  5. Confirm kubelet is healthy on the node:

    sudo systemctl status kubelet -l
  6. Verify that kubelet is no longer using AlwaysAllow and that Webhook mode is in use:

    /bin/ps -fC kubelet

    In the output:

    • You should NOT see --authorization-mode=AlwaysAllow.
    • If using flags, you SHOULD see --authorization-mode=Webhook and --authentication-token-webhook.
    • If using a config file only, you should still not see AlwaysAllow, and you have already set authorization.mode: Webhook in /var/lib/kubelet/config.yaml.
Using kubectl

kubectl cannot change the kubelet’s --authorization-mode or the contents of /var/lib/kubelet/config.yaml, because these are host-level settings managed on each worker node’s OS and systemd units. To remediate this finding, make the changes directly on every worker node as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Fix CISEKS 3.2.2:
# Ensure kubelet authorization mode is not AlwaysAllow and Webhook is enabled.
#
# Run on: every worker node (as root or with sudo).
# Safe to re-run (idempotent).

set -euo pipefail

log() { printf '[%s] %s\n' "$(date -u +%FT%TZ)" "$*"; }

require_root() {
if [ "$(id -u)" -ne 0 ]; then
log "ERROR: This script must be run as root (or via sudo)."
exit 1
fi
}

find_kubelet_config_from_process() {
# Try to get --config from running kubelet
if ! pgrep -x kubelet >/dev/null 2>&1; then
log "ERROR: kubelet process not found; cannot auto-detect config. Aborting."
return 1
fi

local cmdline
cmdline=$(tr '\0' ' ' < /proc/"$(pgrep -x kubelet | head -n1)"/cmdline)

# Extract value of --config=... or --config <path>
if grep -q -- '--config=' <<<"$cmdline"; then
awk '
{
for (i=1; i<=NF; i++) {
if ($i ~ /^--config=/) {
sub(/^--config=/, "", $i);
print $i;
exit;
}
}
}' <<<"$cmdline"
elif grep -q -- '--config ' <<<"$cmdline"; then
# Handle "--config /path"
awk '
{
for (i=1; i<=NF; i++) {
if ($i == "--config") {
print $(i+1);
exit;
}
}
}' <<<"$cmdline"
else
echo ""
fi
}

ensure_kubelet_yaml_authz_webhook() {
local cfg="$1"

if [ ! -f "$cfg" ]; then
log "ERROR: kubelet config file '$cfg' not found."
return 1
fi

log "Using kubelet config file: $cfg"

# Backup once per run
if [ ! -f "${cfg}.cis-3.2.2.bak" ]; then
cp -p "$cfg" "${cfg}.cis-3.2.2.bak"
log "Backup created at ${cfg}.cis-3.2.2.bak"
fi

# Ensure authentication.webhook.enabled: true
if ! grep -qE '^[[:space:]]*authentication:' "$cfg"; then
cat >>"$cfg" <<'EOF'

authentication:
webhook:
enabled: true
EOF
log "Added authentication.webhook.enabled: true block."
elif ! grep -qE '^[[:space:]]*webhook:' "$cfg" || \
! grep -qE '^[[:space:]]*enabled:[[:space:]]*true' "$cfg"; then
# Use a temporary edited file to avoid complex inline YAML tooling
local tmp
tmp=$(mktemp)
awk '
BEGIN {in_auth=0}
/^[[:space:]]*authentication:/ {in_auth=1}
{
if (in_auth && $0 ~ /^[[:space:]]*authorization:/) {
# Insert webhook block before authorization or next section
print "authentication:"
print " webhook:"
print " enabled: true"
in_auth=0
}
print
}
' "$cfg" >"$tmp" || { rm -f "$tmp"; return 1; }
mv "$tmp" "$cfg"
log "Ensured authentication.webhook.enabled: true in existing block."
else
log "authentication.webhook.enabled: true already present."
fi

# Ensure authorization: mode: Webhook
if ! grep -qE '^[[:space:]]*authorization:' "$cfg"; then
cat >>"$cfg" <<'EOF'

authorization:
mode: Webhook
EOF
log "Added authorization.mode: Webhook block."
else
# Normalize mode under authorization
local tmp
tmp=$(mktemp)
awk '
BEGIN {in_authz=0}
/^[[:space:]]*authorization:/ {in_authz=1}
/^[[:space:]]*[A-Za-z]/ && !/^[[:space:]]*authorization:/ && in_authz==1 {
# Next top-level starts, close block
in_authz=0
}
{
if (in_authz && $0 ~ /^[[:space:]]*mode:/) {
sub(/mode:[[:space:]]*.*/, "mode: Webhook");
}
print
}
' "$cfg" >"$tmp" || { rm -f "$tmp"; return 1; }
mv "$tmp" "$cfg"
log "Set authorization.mode: Webhook in existing block."
fi
}

ensure_kubelet_systemd_args() {
local dropin="/etc/systemd/system/kubelet.service.d/10-kubelet-args.conf"

if [ ! -f "$dropin" ]; then
log "No kubelet systemd args drop-in at $dropin; assuming config file method."
return 0
fi

log "Ensuring webhook auth/authorization flags in $dropin"

if ! grep -q -- '--authentication-token-webhook' "$dropin"; then
sed -i 's#KUBELET_ARGS="#KUBELET_ARGS="--authentication-token-webhook #g' "$dropin" || true
if ! grep -q -- '--authentication-token-webhook' "$dropin"; then
echo 'KUBELET_ARGS="--authentication-token-webhook ${KUBELET_ARGS}"' >>"$dropin"
fi
log "Ensured --authentication-token-webhook in KUBELET_ARGS."
else
log "--authentication-token-webhook already present."
fi

if grep -q -- '--authorization-mode=' "$dropin"; then
sed -i 's#--authorization-mode=[^" ]*#--authorization-mode=Webhook#g' "$dropin"
log "Replaced existing --authorization-mode with Webhook."
else
sed -i 's#KUBELET_ARGS="#KUBELET_ARGS="--authorization-mode=Webhook #g' "$dropin" || true
if ! grep -q -- '--authorization-mode=Webhook' "$dropin"; then
echo 'KUBELET_ARGS="--authorization-mode=Webhook ${KUBELET_ARGS}"' >>"$dropin"
fi
log "Ensured --authorization-mode=Webhook in KUBELET_ARGS."
fi
}

restart_kubelet() {
log "Reloading systemd and restarting kubelet..."
systemctl daemon-reload
systemctl restart kubelet.service
systemctl status kubelet -l --no-pager || true
}

verify() {
log "Verification: checking kubelet process flags and config..."

/bin/ps -fC kubelet || {
log "ERROR: kubelet process not found after restart."
return 1
}

local cmdline
cmdline=$(tr '\0' ' ' < /proc/"$(pgrep -x kubelet | head -n1)"/cmdline)
log "kubelet cmdline: $cmdline"

if echo "$cmdline" | grep -q -- '--authorization-mode=AlwaysAllow'; then
log "ERROR: kubelet still running with --authorization-mode=AlwaysAllow"
return 1
fi

if echo "$cmdline" | grep -q -- '--authorization-mode=Webhook'; then
log "OK: kubelet uses --authorization-mode=Webhook flag."
else
log "INFO: kubelet may be using Webhook via config file (no explicit flag)."
fi

# If config file is in use and exists, inspect it for sanity
local cfg
cfg=$(find_kubelet_config_from_process || echo "")
if [ -n "$cfg" ] && [ -f "$cfg" ]; then
log "Inspecting kubelet config file at $cfg"
grep -nE 'authentication:|webhook|authorization:|mode:' "$cfg" || true
fi

log "Verification completed."
}

main() {
require_root

# Prefer config file if present
local cfg
cfg=$(find_kubelet_config_from_process || echo "")

if [ -z "$cfg" ]; then
log "No --config argument detected; using systemd executable-args remediation."
ensure_kubelet_systemd_args
else
ensure_kubelet_yaml_authz_webhook "$cfg"
# Also ensure flags if the environment uses them; harmless if not used.
ensure_kubelet_systemd_args
fi

restart_kubelet
verify
}

main "$@"