Kubelet Authorization Mode Not Set To AlwaysAllow
More Info:
An authorization mode of AlwaysAllow permits every authenticated request without further checks. Using Webhook authorization ensures requests to the kubelet are properly authorized.
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 static pod manifest and open it for editing:
sudo cp /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.baksudo vi /etc/kubernetes/manifests/kube-apiserver.yaml -
In the
kube-apiservercontainercommand/argssection, locate any existing--authorization-mode=flag:- If present and set to
AlwaysAllow, change it to a secure mode, for example:- --authorization-mode=RBAC - If multiple modes are configured, ensure
AlwaysAllowis not among them, for example:- --authorization-mode=Node,RBAC - If the flag is missing, add a new line under the other
--flags:- --authorization-mode=RBAC
- If present and set to
-
Save the file and exit the editor. The kubelet will automatically detect the change to
/etc/kubernetes/manifests/kube-apiserver.yamland restart thekube-apiserverstatic pod. Be aware this temporarily restarts the API server on that control plane node. -
Wait for the
kube-apiserverpod to become Ready again (from any machine withkubectlaccess):kubectl get pods -n kube-system -o wide | grep kube-apiserver -
Repeat steps 1–4 on every control plane node to ensure consistent authorization configuration across the cluster.
-
Verify on each control plane node that the API server is no longer running with
--authorization-mode=AlwaysAllow:/bin/ps -ef | grep kube-apiserver | grep -v grepConfirm that the
kube-apiserverprocess line includes--authorization-mode=and thatAlwaysAllowdoes not appear in its value (e.g., it showsRBACorNode,RBACinstead).
Using kubectl
kubectl cannot modify kube-apiserver startup flags or static pod manifests on the nodes, so this finding cannot be fixed through the Kubernetes API. To remediate it, edit /etc/kubernetes/manifests/kube-apiserver.yaml directly on every control plane node as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Automation for CIS Kubernetes 4.2.2
# Fix: Ensure kube-apiserver --authorization-mode is not set to AlwaysAllow
#
# Usage (run on every control plane node, as root):
# bash fix-kube-apiserver-authorization-mode.sh
#
# Operational impact:
# - Editing /etc/kubernetes/manifests/kube-apiserver.yaml will cause the
# kube-apiserver static pod to restart on this node.
set -euo pipefail
API_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-authorization-mode"
DESIRED_MODE="RBAC"
echo "[INFO] Running on host: $(hostname)"
echo "[INFO] Target manifest: ${API_MANIFEST}"
if [[ ! -f "${API_MANIFEST}" ]]; then
echo "[ERROR] kube-apiserver manifest not found at ${API_MANIFEST}"
echo "[ERROR] This script must be run on a control plane node that uses static pods."
exit 1
fi
mkdir -p "${BACKUP_DIR}"
BACKUP_FILE="${BACKUP_DIR}/kube-apiserver.yaml.$(date +%Y%m%d-%H%M%S)"
cp -a "${API_MANIFEST}" "${BACKUP_FILE}"
echo "[INFO] Backup created at ${BACKUP_FILE}"
# Extract existing authorization-mode value (if any)
CURRENT_MODE_LINE="$(grep -E -- '--authorization-mode=' "${API_MANIFEST}" || true)"
CURRENT_MODE_VALUE=""
if [[ -n "${CURRENT_MODE_LINE}" ]]; then
CURRENT_MODE_VALUE="$(echo "${CURRENT_MODE_LINE}" | sed -E 's/.*--authorization-mode=([^" ]*).*/\1/')"
fi
if [[ "${CURRENT_MODE_VALUE}" == "${DESIRED_MODE}" ]]; then
echo "[INFO] --authorization-mode already set to ${DESIRED_MODE}; no change required."
else
echo "[INFO] Updating --authorization-mode to ${DESIRED_MODE}"
TMP_FILE="$(mktemp)"
trap 'rm -f "${TMP_FILE}"' EXIT
if grep -qE -- '--authorization-mode=' "${API_MANIFEST}"; then
# Replace existing value
sed -E "s/(--authorization-mode=)[^\" ]*/\1${DESIRED_MODE}/" "${API_MANIFEST}" > "${TMP_FILE}"
else
# Add flag under containers.args
# This assumes standard kubeadm-style manifest with containers: and args: lists.
# Insert the new arg right after the first occurrence of "--advertise-address" or at the end of args.
if grep -q -- "--advertise-address" "${API_MANIFEST}"; then
awk -v flag=" - --authorization-mode=${DESIRED_MODE}" '
/--advertise-address/ && !inserted {
print $0
print flag
inserted=1
next
}
{ print $0 }
END {
if (!inserted) {
# Fallback: in case pattern was not matched (defensive)
print flag
}
}
' "${API_MANIFEST}" > "${TMP_FILE}"
else
# Generic fallback: append to the args list of kube-apiserver container
awk -v flag=" - --authorization-mode=${DESIRED_MODE}" '
/name: kube-apiserver/ { in_container=1 }
in_container && /args:/ { in_args=1 }
in_container && in_args && $1 !~ /^-/ && $1 !~ /^args:/ && $1 !~ /^#/ && !inserted {
print flag
inserted=1
}
{ print $0 }
END {
if (!inserted) {
print flag
}
}
' "${API_MANIFEST}" > "${TMP_FILE}"
fi
fi
cp "${TMP_FILE}" "${API_MANIFEST}"
sync
echo "[INFO] Manifest updated. kubelet will restart kube-apiserver static pod automatically."
fi
echo "[INFO] Waiting 30 seconds for kube-apiserver to restart..."
sleep 30
echo "[INFO] Verification: checking running kube-apiserver process"
if ! /bin/ps -ef | grep kube-apiserver | grep -v grep > /dev/null 2>&1; then
echo "[ERROR] kube-apiserver process not found after change; check kubelet and pod status."
exit 1
fi
AUTH_LINE="$(/bin/ps -ef | grep kube-apiserver | grep -v grep | tr -s ' ' | sed -E 's/.*kube-apiserver (.*)/\1/' | tr ' ' '\n' | grep '^--authorization-mode=' || true)"
if [[ -z "${AUTH_LINE}" ]]; then
echo "[WARN] --authorization-mode flag not visible in process arguments."
echo "[WARN] Ensure authorization is configured via config file and not using AlwaysAllow."
else
AUTH_VALUE="${AUTH_LINE#--authorization-mode=}"
if [[ "${AUTH_VALUE}" == "AlwaysAllow" ]]; then
echo "[ERROR] kube-apiserver is still using --authorization-mode=AlwaysAllow"
exit 1
fi
echo "[INFO] kube-apiserver --authorization-mode is now set to: ${AUTH_VALUE}"
fi
echo "[INFO] Remediation verification completed."