> ## 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.

# API Server Audit Log Maxbackup Should Be 10 Or More

### More Info:

Verifies that --audit-log-maxbackup is set to 10 or an appropriate value so enough old audit log files are retained.

### Risk Level

Medium

### 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 API server 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 kube-apiserver static pod manifest to set `--audit-log-maxbackup` (this edit triggers an automatic kube-apiserver restart):
           ```bash theme={null}
           sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
           ```
           In the `command:` or `args:` list for `kube-apiserver`, add or update this flag to an appropriate value (10 or higher), for example:
           ```yaml theme={null}
           - --audit-log-maxbackup=10
           ```

        3. Save the file and exit the editor; wait 30–60 seconds for the kubelet to detect the manifest change and restart the `kube-apiserver` static pod.

        4. On the same control plane node, confirm the API server process is running with the desired `--audit-log-maxbackup` value:
           ```bash theme={null}
           /bin/ps -ef | grep kube-apiserver | grep -v grep
           ```
           Ensure the output includes:
           ```text theme={null}
           --audit-log-maxbackup=10
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the API server’s static pod manifest or its process flags, so this finding cannot be fixed via the Kubernetes API. The required change must be made directly on each control plane node in `/etc/kubernetes/manifests/kube-apiserver.yaml`; see the Manual Steps section for the exact procedure.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Remediation: Ensure kube-apiserver --audit-log-maxbackup is set to >= 10
        # Scope: Run on every control plane node (as root)

        set -euo pipefail

        APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
        MIN_VALUE=10
        TMP_SUFFIX=".$$.tmp"

        if [ ! -f "$APISERVER_MANIFEST" ]; then
          echo "ERROR: $APISERVER_MANIFEST not found on this node. Are you on a control plane node?"
          exit 1
        fi

        if ! command -v python3 >/dev/null 2>&1; then
          echo "ERROR: python3 is required for safe YAML editing."
          exit 1
        fi

        # 1) Backup once per node (idempotent if re-run)
        BACKUP="${APISERVER_MANIFEST}.backup"
        if [ ! -f "$BACKUP" ]; then
          cp -p "$APISERVER_MANIFEST" "$BACKUP"
          echo "Backup created at $BACKUP"
        else
          echo "Backup already exists at $BACKUP"
        fi

        # 2) Use Python to enforce --audit-log-maxbackup >= MIN_VALUE in the container args
        python3 << 'EOF'
        import sys, re, shutil, os
        from pathlib import Path

        manifest_path = Path("/etc/kubernetes/manifests/kube-apiserver.yaml")
        min_value = 10

        try:
            import yaml  # type: ignore
        except Exception:
            yaml = None

        content = manifest_path.read_text()

        if yaml is None:
            # Fallback: regex-based edit on --audit-log-maxbackup=
            pattern = re.compile(r'(--audit-log-maxbackup=)(\d+)\b')
            m = pattern.search(content)
            if m:
                current = int(m.group(2))
                if current >= min_value:
                    sys.exit(0)
                new = f"{m.group(1)}{min_value}"
                new_content = pattern.sub(new, content, count=1)
            else:
                # Try to inject into a line with kube-apiserver command
                lines = content.splitlines()
                inserted = False
                for i, line in enumerate(lines):
                    if "kube-apiserver" in line and "command:" in content:
                        # For command-based spec, we won't try to auto-edit safely without YAML
                        break
                    if "kube-apiserver" in line and "--secure-port" in line:
                        # args-style single line; append new arg
                        indent = re.match(r'^(\s*)', line).group(1)
                        lines.insert(i + 1, f'{indent}- --audit-log-maxbackup={min_value}')
                        inserted = True
                        break
                if not inserted:
                    # As a last resort, append under first 'args:' section
                    for i, line in enumerate(lines):
                        if re.match(r'^\s*args:\s*$', line):
                            indent = re.match(r'^(\s*)', lines[i+1]).group(1)
                            lines.insert(i + 1, f'{indent}- --audit-log-maxbackup={min_value}')
                            inserted = True
                            break
                if not inserted:
                    print("ERROR: Could not safely inject --audit-log-maxbackup without PyYAML.", file=sys.stderr)
                    sys.exit(1)
                new_content = "\n".join(lines)

            tmp_path = str(manifest_path) + ".tmp"
            with open(tmp_path, "w") as f:
                f.write(new_content)
            os.replace(tmp_path, manifest_path)
            sys.exit(0)

        # YAML-based edit (preferred)
        with open(manifest_path) as f:
            data = yaml.safe_load(f)

        spec = data.get("spec", {})
        containers = spec.get("containers", [])
        if not containers:
            print("ERROR: No containers found in kube-apiserver manifest.", file=sys.stderr)
            sys.exit(1)

        api = containers[0]
        args = api.get("args", [])

        # Normalize existing values, if any
        new_args = []
        found = False
        for arg in args:
            if isinstance(arg, str) and arg.startswith("--audit-log-maxbackup="):
                try:
                    cur = int(arg.split("=", 1)[1])
                except ValueError:
                    cur = min_value
                if cur < min_value:
                    arg = f"--audit-log-maxbackup={min_value}"
                found = True
            new_args.append(arg)

        if not found:
            new_args.append(f"--audit-log-maxbackup={min_value}")

        # If nothing changed and already >= min_value, exit without rewrite
        if args == new_args:
            sys.exit(0)

        api["args"] = new_args
        spec["containers"] = [api]
        data["spec"] = spec

        tmp_path = str(manifest_path) + ".tmp"
        with open(tmp_path, "w") as f:
            yaml.safe_dump(data, f, default_flow_style=False)
        os.replace(tmp_path, manifest_path)
        EOF

        echo "Updated $APISERVER_MANIFEST; kubelet will restart kube-apiserver static pod automatically."

        # 3) Wait for kube-apiserver to restart and stabilize
        echo "Waiting up to 120s for kube-apiserver process to be running with new flag..."
        end=$((SECONDS+120))
        while [ $SECONDS -lt $end ]; do
          if /bin/ps -ef | grep kube-apiserver | grep -v grep >/dev/null 2>&1; then
            break
          fi
          sleep 3
        done

        # 4) Verification (same basis as audit command)
        /bin/ps -ef | grep kube-apiserver | grep -v grep

        # Additional verification of the flag value
        echo
        echo "Verifying --audit-log-maxbackup is set to at least ${MIN_VALUE}:"
        if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- '--audit-log-maxbackup=' >/dev/null 2>&1; then
          /bin/ps -ef | grep kube-apiserver | grep -v grep | tr -s ' ' | \
            sed 's/ /\n/g' | grep -- '^--audit-log-maxbackup=' || true
        else
          echo "ERROR: kube-apiserver is running but --audit-log-maxbackup flag not found in process list."
          exit 1
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
