API Server Authorization Mode Should Not Be AlwaysAllow
More Info:
Verifies that --authorization-mode does not include AlwaysAllow. AlwaysAllow authorizes every request and effectively disables access control.
Risk Level
Critical
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
- On every control plane node, back up the API server manifest:
sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak
- On every control plane node, open the manifest for editing:
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
- In the
command:orargs:section of the kube-apiserver container, locate any--authorization-modeentry that includesAlwaysAllowand change it to excludeAlwaysAllow, for example:
- --authorization-mode=Node,RBAC
If --authorization-mode is missing, add a line like the above under the kube-apiserver container args. Save and exit.
Note: editing this file will cause the kube-apiserver static pod to restart automatically.
- Wait 30–60 seconds and confirm the kube-apiserver pod is running and ready (from any machine with kubectl access):
kubectl -n kube-system get pod -l component=kube-apiserver -o wide
- On every control plane node, verify the running process no longer uses
AlwaysAllow:
/bin/ps -ef | grep kube-apiserver | grep -v grep
- In the output, ensure the
kube-apiservercommand line contains--authorization-modewithoutAlwaysAllow(for example--authorization-mode=Node,RBAC) and thatAlwaysAllowdoes not appear anywhere in the arguments.
Using kubectl
kubectl cannot modify the API server’s static pod manifest or process flags, so this finding cannot be fixed through the Kubernetes API. To remediate, you must edit /etc/kubernetes/manifests/kube-apiserver.yaml directly on every control plane node; see the Manual Steps section for detailed guidance.
Automation
#!/usr/bin/env bash
#
# Fix CIS 4.2.2: Ensure kube-apiserver is not using AlwaysAllow authorization mode
# Target: every control plane node
#
# Usage: run as root on each control plane node:
# bash fix-apiserver-authorization-mode.sh
#
# Operational impact:
# - Editing /etc/kubernetes/manifests/kube-apiserver.yaml will restart the kube-apiserver
# static pod via kubelet. Expect a brief control-plane API disruption.
set -euo pipefail
APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-$(date +%Y%m%d-%H%M%S)"
TARGET_MODE="RBAC" # Change if you need a different non-AlwaysAllow mode
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] Manifest not found at $APISERVER_MANIFEST. This script is only for static pod setups." >&2
exit 1
fi
# Backup
echo "[INFO] Creating backup of kube-apiserver manifest in $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
cp -p "$APISERVER_MANIFEST" "$BACKUP_DIR/kube-apiserver.yaml"
# Function: update or insert --authorization-mode flag
update_authorization_mode() {
local tmpfile
tmpfile="$(mktemp)"
# Strategy:
# 1. If an --authorization-mode flag exists, replace its value with TARGET_MODE,
# and ensure AlwaysAllow is not present.
# 2. If it does not exist, append a new - --authorization-mode=TARGET_MODE
# under the "command:" section.
# First, detect if a line with --authorization-mode exists
if grep -q -- "--authorization-mode" "$APISERVER_MANIFEST"; then
echo "[INFO] Existing --authorization-mode flag found; updating"
# Replace any existing --authorization-mode=... with exactly TARGET_MODE
# and remove any occurrence of AlwaysAllow.
# Handles both "- --authorization-mode=Something" and
# "- --authorization-mode=RBAC,Something"
awk -v tgt="$TARGET_MODE" '
{
if ($0 ~ /--authorization-mode/) {
# Normalize entire flag to only tgt
sub(/--authorization-mode=[^[:space:]]+/, "--authorization-mode=" tgt)
}
print
}
' "$APISERVER_MANIFEST" > "$tmpfile"
else
echo "[INFO] No existing --authorization-mode flag; inserting"
# Insert the new flag under the "command:" list
awk -v tgt="$TARGET_MODE" '
/command:/ && in_container == 0 {
in_command = 1
}
/- kube-apiserver/ && in_command == 1 {
in_container = 1
}
{
print
if (in_container == 1 && $1 ~ /^-$/ && $2 ~ /^--/) {
# We are in the list of flags; insert once before the first flag
print " - --authorization-mode=" tgt
in_container = 2
}
}
' "$APISERVER_MANIFEST" > "$tmpfile"
# Fallback: if insertion heuristic failed (no change), append near command
if ! grep -q -- "--authorization-mode=${TARGET_MODE}" "$tmpfile"; then
echo "[WARN] Heuristic insertion failed; appending --authorization-mode to manifest"
awk -v tgt="$TARGET_MODE" '
/- kube-apiserver/ && appended == 0 {
print
print " - --authorization-mode=" tgt
appended = 1
next
}
{ print }
' "$APISERVER_MANIFEST" > "$tmpfile"
fi
fi
mv "$tmpfile" "$APISERVER_MANIFEST"
}
update_authorization_mode
echo "[INFO] Updated $APISERVER_MANIFEST. kubelet will restart kube-apiserver automatically."
# Wait for kube-apiserver process to restart and reflect new flags
echo "[INFO] Waiting for kube-apiserver to restart with new authorization-mode flag..."
RETRIES=30
SLEEP_SECONDS=5
success=0
for i in $(seq 1 $RETRIES); do
if /bin/ps -ef | grep kube-apiserver | grep -v grep >/dev/null 2>&1; then
# Verify that AlwaysAllow is not present and TARGET_MODE is present
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--authorization-mode"; then
if ! /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "AlwaysAllow"; then
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--authorization-mode=${TARGET_MODE}"; then
success=1
break
fi
fi
fi
fi
echo "[INFO] Attempt $i/$RETRIES: kube-apiserver not yet running with desired flags; retrying in $SLEEP_SECONDS seconds..."
sleep "$SLEEP_SECONDS"
done
echo "[INFO] Final verification:"
/bin/ps -ef | grep kube-apiserver | grep -v grep || true
if [[ "$success" -eq 1 ]]; then
echo "[SUCCESS] kube-apiserver is running without AlwaysAllow and with --authorization-mode=${TARGET_MODE}"
exit 0
else
echo "[ERROR] Failed to verify kube-apiserver is using --authorization-mode=${TARGET_MODE} without AlwaysAllow." >&2
echo "[ERROR] Please review $APISERVER_MANIFEST and kubelet/kube-apiserver logs." >&2
exit 1
fi