Skip to main content

API Server Audit Log Maxsize Should Be 100 Or More

More Info:

Verifies that --audit-log-maxsize is set to 100 MB or an appropriate value to control rotation of audit log files.

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 manifest before editing:

    sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak
  2. On every control plane node, edit the API server manifest to set the audit log max size (example: 100 MB):

    sudo sed -i 's@^\(\s*-\s*--audit-log-maxsize=\).*@\1100@' /etc/kubernetes/manifests/kube-apiserver.yaml

    If the flag does not exist, add this line under the command: section with the other - -- flags:

    sudo sed -i '/kube-apiserver$/a\ \ \ \ - --audit-log-maxsize=100' /etc/kubernetes/manifests/kube-apiserver.yaml
  3. Wait for the kubelet on each control plane node to automatically restart the kube-apiserver static pod after the manifest change (this happens automatically; no manual restart command is needed). Be aware this briefly restarts the API server on that node.

  4. Verify on every control plane node that the API server is running with the correct --audit-log-maxsize value:

    /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- '--audit-log-maxsize=100'

    The command should return a line showing --audit-log-maxsize=100 in the kube-apiserver process arguments.

Using kubectl

kubectl cannot modify the kube-apiserver static pod manifest or its process flags, so this finding cannot be fixed via the Kubernetes API. The --audit-log-maxsize setting must be changed directly in /etc/kubernetes/manifests/kube-apiserver.yaml on every control plane node; follow the Manual Steps section to make and verify that change.

Automation
#!/usr/bin/env bash
#
# Automation: Ensure kube-apiserver --audit-log-maxsize >= 100
#
# Usage:
# Run on every control plane node as root:
# sudo bash ./fix-apiserver-audit-log-maxsize.sh
#
# This script is idempotent and safe to re-run.

set -euo pipefail

APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
MIN_SIZE=100

echo "==> Checking for kube-apiserver manifest at ${APISERVER_MANIFEST}"
if [[ ! -f "${APISERVER_MANIFEST}" ]]; then
echo "ERROR: ${APISERVER_MANIFEST} not found on this node. This script must run on a control plane node."
exit 1
fi

# Create a timestamped backup once per run (ok if re-run; multiple backups are fine)
BACKUP="${APISERVER_MANIFEST}.$(date +%Y%m%d%H%M%S).bak"
cp "${APISERVER_MANIFEST}" "${BACKUP}"
echo "==> Backup created: ${BACKUP}"

# Extract current value if present
CURRENT_VAL_RAW=$(grep -E -- '--audit-log-maxsize=' "${APISERVER_MANIFEST}" 2>/dev/null || true)

CURRENT_VAL=""
if [[ -n "${CURRENT_VAL_RAW}" ]]; then
# Handle forms like:
# - --audit-log-maxsize=100
# - - --audit-log-maxsize=100 (with leading YAML dash)
CURRENT_VAL=$(echo "${CURRENT_VAL_RAW}" | sed -E 's/.*--audit-log-maxsize=([0-9]+).*/\1/' | head -n1 || true)
fi

need_change=false

if [[ -z "${CURRENT_VAL}" ]]; then
echo "==> --audit-log-maxsize not currently set; will add with value ${MIN_SIZE}"
need_change=true
elif [[ "${CURRENT_VAL}" -lt "${MIN_SIZE}" ]]; then
echo "==> --audit-log-maxsize currently ${CURRENT_VAL}, which is < ${MIN_SIZE}; will update to ${MIN_SIZE}"
need_change=true
else
echo "==> --audit-log-maxsize currently ${CURRENT_VAL}, which is >= ${MIN_SIZE}; no change needed."
fi

if [[ "${need_change}" == true ]]; then
TMP_FILE="$(mktemp)"
echo "==> Updating ${APISERVER_MANIFEST}"

if grep -q -- '--audit-log-maxsize=' "${APISERVER_MANIFEST}"; then
# Replace existing value with MIN_SIZE
sed -E "s/(--audit-log-maxsize=)[0-9]+/\1${MIN_SIZE}/" "${APISERVER_MANIFEST}" > "${TMP_FILE}"
else
# Insert new flag on its own line under other --audit-log-* or generic args
#
# Strategy: append a new argument line right after the last existing --audit-log-* flag
# if present, otherwise after the last apiserver argument line (starting with ' - --').
if grep -qE '^\s*-\s*--audit-log-' "${APISERVER_MANIFEST}"; then
# After last --audit-log-* line
awk -v minsize="${MIN_SIZE}" '
/^\s*-\s*--audit-log-/ { last_audit_line=NR }
{ lines[NR]=$0 }
END {
for (i=1; i<=NR; i++) {
print lines[i]
if (i==last_audit_line) {
print gensub(/^( *).*/, "\\1- --audit-log-maxsize=" minsize, 1, lines[i])
}
}
}
' "${APISERVER_MANIFEST}" > "${TMP_FILE}"
else
# After last generic arg line
awk -v minsize="${MIN_SIZE}" '
/^\s*-\s*--/ { last_arg_line=NR }
{ lines[NR]=$0 }
END {
for (i=1; i<=NR; i++) {
print lines[i]
if (i==last_arg_line) {
print gensub(/^( *).*/, "\\1- --audit-log-maxsize=" minsize, 1, lines[i])
}
}
}
' "${APISERVER_MANIFEST}" > "${TMP_FILE}"
fi
fi

# Basic sanity check: ensure the resulting file still has apiServer container definition
if ! grep -q "kube-apiserver" "${TMP_FILE}"; then
echo "ERROR: Modified manifest does not contain kube-apiserver; refusing to overwrite."
rm -f "${TMP_FILE}"
exit 1
fi

mv "${TMP_FILE}" "${APISERVER_MANIFEST}"
echo "==> Updated ${APISERVER_MANIFEST} with --audit-log-maxsize=${MIN_SIZE}"

echo "==> kube-apiserver static pod will be restarted automatically by the kubelet."
fi

echo "==> Waiting for kube-apiserver process to reflect new arguments..."
sleep 10

echo "==> Verification (ps -ef | grep kube-apiserver | grep -v grep)"
ps -ef | grep kube-apiserver | grep -v grep || {
echo "ERROR: kube-apiserver process not found after change."
exit 1
}

echo
echo "==> Checking for --audit-log-maxsize >= ${MIN_SIZE} in running process:"
ps -ef | grep kube-apiserver | grep -v grep | tr ' ' '\n' | grep -- '--audit-log-maxsize=' || {
echo "ERROR: --audit-log-maxsize flag not found in running kube-apiserver."
exit 1
}

RUNNING_VAL=$(ps -ef | grep kube-apiserver | grep -v grep | tr ' ' '\n' | grep -- '--audit-log-maxsize=' | sed -E 's/.*--audit-log-maxsize=([0-9]+).*/\1/' | head -n1 || true)

if [[ -z "${RUNNING_VAL}" || "${RUNNING_VAL}" -lt "${MIN_SIZE}" ]]; then
echo "ERROR: Running kube-apiserver --audit-log-maxsize is '${RUNNING_VAL}', expected >= ${MIN_SIZE}."
exit 1
fi

echo "==> Success: running kube-apiserver has --audit-log-maxsize=${RUNNING_VAL} (>= ${MIN_SIZE})."