Skip to main content

Ensure Authorization Mode Argument Is Not AlwaysAllow

More Info:

Do not allow all requests. Enable explicit authorization.

Risk Level

Medium

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. On every control plane node, back up the current API server static pod manifest:

    sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak.$(date +%F-%H%M%S)
  2. On every control plane node, edit the API server manifest to remove AlwaysAllow and enable RBAC (this edit will automatically restart the kube-apiserver when the file is saved):

    sudo sed -i 's/--authorization-mode=AlwaysAllow/--authorization-mode=RBAC/' /etc/kubernetes/manifests/kube-apiserver.yaml

    If --authorization-mode is missing or contains a list including AlwaysAllow, edit the file manually:

    sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml

    and ensure there is a line under containers: -> kube-apiserver -> command: similar to:

    - --authorization-mode=RBAC
  3. Wait for the kubelet on the control plane node to detect the modified manifest and restart the kube-apiserver container (this is automatic and briefly disrupts API server availability).

  4. Verify on every control plane node that the kube-apiserver is no longer using AlwaysAllow and is using RBAC instead:

    /bin/ps -ef | grep kube-apiserver | grep -v grep

    Confirm the kube-apiserver process includes --authorization-mode=RBAC and does not contain --authorization-mode=AlwaysAllow.

Using kubectl

kubectl cannot change the API server’s --authorization-mode flag because it is configured via the static pod manifest on each control plane node, not through Kubernetes API objects. To fix this finding, edit /etc/kubernetes/manifests/kube-apiserver.yaml on every control plane node as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Automation: Fix kube-apiserver --authorization-mode so it is not AlwaysAllow
#
# Run on: every control plane node (with root privileges)
#
# This script:
# - Backs up /etc/kubernetes/manifests/kube-apiserver.yaml
# - Ensures --authorization-mode does not contain AlwaysAllow
# - Sets a sane default (--authorization-mode=RBAC) if none is present
# - Leaves other existing authorization modes intact (except AlwaysAllow)
# - Triggers kube-apiserver restart via static pod manifest update
# - Verifies the running process arguments no longer use AlwaysAllow
#
# Usage: sudo bash ./fix-authorization-mode.sh

set -euo pipefail

APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_SUFFIX="$(date +%Y%m%d%H%M%S)"

echo "[INFO] Starting kube-apiserver authorization-mode remediation"

if [[ $EUID -ne 0 ]]; then
echo "[ERROR] This script must be run as root." >&2
exit 1
fi

if [[ ! -f "$APISERVER_MANIFEST" ]]; then
echo "[ERROR] kube-apiserver manifest not found at $APISERVER_MANIFEST" >&2
exit 1
fi

echo "[INFO] Backing up existing manifest to ${APISERVER_MANIFEST}.bak.${BACKUP_SUFFIX}"
cp -p "$APISERVER_MANIFEST" "${APISERVER_MANIFEST}.bak.${BACKUP_SUFFIX}"

TMP_MANIFEST="$(mktemp)"
cp "$APISERVER_MANIFEST" "$TMP_MANIFEST"

# Normalize line endings just in case
dos2unix "$TMP_MANIFEST" >/dev/null 2>&1 || true

# Function to update the authorization-mode line within a given file
update_authorization_mode() {
local file="$1"

# 1) Remove any occurrence of AlwaysAllow from an existing --authorization-mode arg
# while preserving other modes and separators.
# Examples handled:
# --authorization-mode=AlwaysAllow
# --authorization-mode=AlwaysAllow,RBAC
# --authorization-mode=RBAC,AlwaysAllow,Webhook
#
# Approach:
# - Extract value after '='
# - Split on comma, drop AlwaysAllow, rejoin
# - If result empty, set to RBAC

# First, see if a --authorization-mode flag exists at all.
if grep -q -- '--authorization-mode=' "$file"; then
# Use a small awk program to safely transform the value.
awk '
{
changed = 0
for (i = 1; i <= NF; i++) {
if ($i ~ /--authorization-mode=/) {
split($i, kv, "=")
modes = kv[2]
n = split(modes, arr, ",")
newmodes = ""
for (j = 1; j <= n; j++) {
if (arr[j] != "AlwaysAllow" && arr[j] != "") {
if (newmodes == "") {
newmodes = arr[j]
} else {
newmodes = newmodes "," arr[j]
}
}
}
if (newmodes == "") {
newmodes = "RBAC"
}
$i = kv[1] "=" newmodes
changed = 1
}
}
print $0
}
' "$file" > "${file}.tmp_auth" && mv "${file}.tmp_auth" "$file"
else
# No existing --authorization-mode; append a new argument line in the args list.
# This is conservative and will work for standard kubeadm-style manifests.
# We will add:
# - --authorization-mode=RBAC
#
# Insert it after the first occurrence of "kube-apiserver" container args list.
awk '
$0 ~ /- name: kube-apiserver/ { in_apiserver = 1 }
in_apiserver && $0 ~ /args:/ { in_args = 1 }
in_args && $0 ~ /^ *- --/ && !added {
print $0
print gensub(/.*/, " - --authorization-mode=RBAC", 1)
added = 1
next
}
{ print $0 }
' "$file" > "${file}.tmp_auth" && mv "${file}.tmp_auth" "$file"

# As a fallback (if we somehow did not manage to add it in the block above),
# ensure the flag exists somewhere in the file.
if ! grep -q -- '--authorization-mode=' "$file"; then
echo "[WARN] Could not detect args block structure; appending --authorization-mode=RBAC to manifest."
printf '\n - --authorization-mode=RBAC\n' >> "$file"
fi
fi
}

echo "[INFO] Updating --authorization-mode in manifest"
update_authorization_mode "$TMP_MANIFEST"

# Confirm we have no AlwaysAllow in the manifest anymore
if grep -q 'authorization-mode=.*AlwaysAllow' "$TMP_MANIFEST"; then
echo "[ERROR] Failed to remove AlwaysAllow from manifest; aborting." >&2
rm -f "$TMP_MANIFEST"
exit 1
fi

echo "[INFO] Writing updated manifest back to $APISERVER_MANIFEST"
cp "$TMP_MANIFEST" "$APISERVER_MANIFEST"
rm -f "$TMP_MANIFEST"

echo "[INFO] kube-apiserver static pod manifest updated."
echo "[INFO] NOTE: kubelet will restart the kube-apiserver pod automatically based on this change."

# Wait for process to restart and stabilize
echo "[INFO] Waiting for kube-apiserver to restart..."
sleep 30

# Verification: ensure running kube-apiserver process does not use AlwaysAllow
echo "[INFO] Verifying that --authorization-mode is not AlwaysAllow in running process"
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q 'authorization-mode=.*AlwaysAllow'; then
echo "[ERROR] kube-apiserver still running with AlwaysAllow in --authorization-mode." >&2
echo "[ERROR] Inspect process with:" >&2
echo " /bin/ps -ef | grep kube-apiserver | grep -v grep" >&2
exit 1
fi

# Also confirm we now have some authorization-mode flag present
if ! /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q 'authorization-mode='; then
echo "[WARN] kube-apiserver process does not show an --authorization-mode flag; check component configuration." >&2
else
echo "[INFO] kube-apiserver authorization-mode configured without AlwaysAllow."
fi

echo "[INFO] Remediation complete."

Additional Reading: