> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On every control plane node, back up the existing manifest before editing:

        ```bash theme={null}
        sudo cp -p /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak
        ```

        2. Edit the API server manifest to set the audit log max size (example: 100 MB):

        ```bash theme={null}
        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:

        ```bash theme={null}
        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
        ```

        3. Wait for the kubelet on the control plane node to detect the changed static pod manifest and restart the `kube-apiserver` pod automatically. This restart is expected and will temporarily affect the API server on that node.

        4. Verify on the same control plane node that the `kube-apiserver` process is running with the desired `--audit-log-maxsize` value (replace `100` below if you chose a different value):

        ```bash theme={null}
        /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- '--audit-log-maxsize=100'
        ```
      </Accordion>

      <Accordion title="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.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/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
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://github.com/kubernetes/features/issues/22](https://github.com/kubernetes/features/issues/22)
