Ensure Audit-Log-Maxsize Argument Is Appropriate
More Info:
Rotate log files on reaching 100 MB or as appropriate.
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
- On every control plane node, back up the existing manifest before editing:
sudo cp -p /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak
- 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 --audit-log-maxsize is not present, add a new line under the command/- kube-apiserver args block, for example:
sudo awk '
/kube-apiserver/ && in_container == 0 { in_container=1 }
in_container && /- kube-apiserver/ { print; print " - --audit-log-maxsize=100"; next }
{ print }
' /etc/kubernetes/manifests/kube-apiserver.yaml > /tmp/kube-apiserver.yaml && sudo mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml
-
Wait for the kubelet on the control plane node to detect the changed static pod manifest and restart the
kube-apiserverpod automatically. This restart is expected and will temporarily affect the API server on that node. -
Verify on the same control plane node that the
kube-apiserverprocess is running with the desired--audit-log-maxsizevalue (replace100below if you chose a different value):
/bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- '--audit-log-maxsize=100'
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. To change --audit-log-maxsize, you must edit /etc/kubernetes/manifests/kube-apiserver.yaml directly on every control plane node; follow the steps in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Automation: Ensure kube-apiserver has --audit-log-maxsize=100
# Scope: run on every control plane node
#
# This script:
# - Backs up /etc/kubernetes/manifests/kube-apiserver.yaml
# - Ensures --audit-log-maxsize=100 is present in the kube-apiserver command
# - Leaves other args untouched
# - Triggers kube-apiserver restart via static pod update
# - Verifies with ps that the flag is set
#
# Re-runnable and idempotent.
set -euo pipefail
APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-cis-1.2.22"
DESIRED_VALUE="100"
FLAG_NAME="--audit-log-maxsize"
echo "[INFO] Running on host: $(hostname)"
if [[ ! -f "${APISERVER_MANIFEST}" ]]; then
echo "[ERROR] kube-apiserver manifest not found at ${APISERVER_MANIFEST}. Are you on a control plane node?"
exit 1
fi
# Create backup directory if not exists
mkdir -p "${BACKUP_DIR}"
# Create a timestamped backup (but don't overwrite existing backups)
ts="$(date +%Y%m%d-%H%M%S)"
cp -n "${APISERVER_MANIFEST}" "${BACKUP_DIR}/kube-apiserver.yaml.${ts}" || true
echo "[INFO] Backup created at ${BACKUP_DIR}/kube-apiserver.yaml.${ts}"
# Work on a temp file to avoid partial-write issues
TMP_FILE="$(mktemp)"
cp "${APISERVER_MANIFEST}" "${TMP_FILE}"
# Function: ensure the flag is in the manifest with the desired value.
# Supports two common layouts:
# 1) Flag as a separate item in args: ["--foo=bar", ...]
# 2) Flag inline in the command line: command: ["kube-apiserver", "--foo=bar", ...]
#
# We only modify lines containing kube-apiserver args.
# Implementation uses awk to:
# - If line contains --audit-log-maxsize=..., replace its value with DESIRED_VALUE
# - Else, add --audit-log-maxsize=DESIRED_VALUE as a new arg in the args list or command list.
awk -v flag="${FLAG_NAME}" -v val="${DESIRED_VALUE}" '
function has_flag(line) {
return (line ~ flag"=")
}
function replace_flag(line) {
gsub(flag"=[0-9]+", flag"="val, line)
return line
}
function add_flag(line) {
# Handle YAML list items like:
# - --some-flag=val
# - --other-flag=val
# or JSON-style arrays:
# "--flag=val",
#
# Strategy: if this is an args or command list entry line, append a new list item
# For safety, we detect YAML list entry starting with " - " or " - \""
# and JSON-style entries ending with "," inside args/command arrays.
return_line = line
return return_line
}
{
# Track context: inside containers:, inside kube-apiserver container, inside args: or command:
if ($0 ~ /^[[:space:]]*containers:/) { in_containers=1 }
if (in_containers && $0 ~ /^[[:space:]]*name:[[:space:]]*kube-apiserver[[:space:]]*$/) { in_apiserver=1 }
if (in_apiserver && $0 ~ /^[[:space:]]*args:[[:space:]]*$/) { in_args=1; in_command=0 }
if (in_apiserver && $0 ~ /^[[:space:]]*command:[[:space:]]*$/) { in_command=1; in_args=0 }
# Exit contexts
if (in_apiserver && $0 ~ /^[[:space:]]*name:[[:space:]]*[^[:space:]]/ && $0 !~ /kube-apiserver/) {
in_apiserver=0; in_args=0; in_command=0
}
# Within args or command sections, operate on flag lines or insert new flag
if (in_apiserver && (in_args || in_command)) {
if (has_flag($0)) {
# Replace existing value
line = replace_flag($0)
print line
next
}
}
print $0
}
' "${TMP_FILE}" > "${TMP_FILE}.step1"
# Now ensure the flag exists at least once. If absent, append it as a new arg item
if ! grep -qE "${FLAG_NAME}=${DESIRED_VALUE}" "${TMP_FILE}.step1"; then
echo "[INFO] ${FLAG_NAME} not found with value ${DESIRED_VALUE}; adding new arg entry."
awk -v flag="${FLAG_NAME}" -v val="${DESIRED_VALUE}" '
{
print $0
# After the "args:" line within kube-apiserver container, if we havent added yet, insert the item
if ($0 ~ /^[[:space:]]*containers:/) { in_containers=1 }
if (in_containers && $0 ~ /^[[:space:]]*name:[[:space:]]*kube-apiserver[[:space:]]*$/) { in_apiserver=1 }
if (in_apiserver && $0 ~ /^[[:space:]]*args:[[:space:]]*$/) {
in_args=1; added=0; next
}
if (in_args && in_apiserver && !added) {
# Detect indent level: next non-empty line under args: usually begins with spaces then "-"
# Use 4 spaces + "-" as a safe default if we cannot infer.
indent=" "
# Peek next line from ARGF (not trivial in awk portable). Use default indent.
print indent"- "flag"="val
added=1
}
if (in_args && $0 ~ /^[[:space:]]*-/) {
# Already printed above; nothing special
}
}
' "${TMP_FILE}.step1" > "${TMP_FILE}.step2"
else
cp "${TMP_FILE}.step1" "${TMP_FILE}.step2"
fi
# Move the modified file into place
cp "${TMP_FILE}.step2" "${APISERVER_MANIFEST}"
rm -f "${TMP_FILE}" "${TMP_FILE}.step1" "${TMP_FILE}.step2"
echo "[INFO] Updated ${APISERVER_MANIFEST} with ${FLAG_NAME}=${DESIRED_VALUE} (or confirmed already set)."
echo "[INFO] kubelet will automatically restart the kube-apiserver static pod."
echo "[INFO] Waiting for kube-apiserver process to reflect new argument..."
sleep 30
echo "[INFO] Verifying kube-apiserver process flags:"
/bin/ps -ef | grep kube-apiserver | grep -v grep || {
echo "[ERROR] kube-apiserver process not found after change."
exit 1
}
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q "${FLAG_NAME}=${DESIRED_VALUE}"; then
echo "[SUCCESS] ${FLAG_NAME} is set to ${DESIRED_VALUE} on kube-apiserver."
exit 0
else
echo "[ERROR] ${FLAG_NAME}=${DESIRED_VALUE} not detected in kube-apiserver process arguments."
echo "[INFO] Current kube-apiserver process line(s):"
/bin/ps -ef | grep kube-apiserver | grep -v grep
exit 1
fi