> ## 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 Minimal Audit Policy Is Created

### More Info:

Kubernetes can audit the details of requests made to the API server. The --auditpolicy-file flag must be set for this logging to be enabled.

### Risk Level

Low

### Address

Security

### Compliance Standards

* CIS GKE

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On any machine with `gcloud` and project access, list clusters and identify the affected one:
           ```bash theme={null}
           gcloud container clusters list \
             --project YOUR_PROJECT_ID \
             --format='table(name,location,releaseChannel.channel,loggingConfig.componentConfig.enableComponents)'
           ```

        2. For the specific cluster, confirm current logging/audit-related configuration:
           ```bash theme={null}
           gcloud container clusters describe YOUR_CLUSTER_NAME \
             --region YOUR_CLUSTER_REGION \
             --project YOUR_PROJECT_ID \
             --format='yaml(name,loggingService,loggingConfig,masterAuthorizedNetworksConfig,addonsConfig)'
           ```

        3. Review whether cluster or organization logging requirements (e.g., needing API audit equivalents) are documented, and compare them with what GKE provides (Cloud Audit Logs for Kubernetes):
           * Check if “Admin Activity”, “Data Access”, and “System Event” logs are enabled for the project/folders/org in Cloud Logging / Cloud Audit Logs.
           * Confirm with your security/compliance policy whether GKE’s managed audit/logging features are acceptable as the “minimal audit policy” for your environment.

        4. In the Google Cloud console, navigate to **Logging → Logs Explorer**, and verify that Kubernetes API–related events are appearing:
           * Use a query such as:
             ```text theme={null}
             logName:"cloudaudit.googleapis.com" 
             protoPayload.serviceName="k8s.io"
             ```
           * Optionally filter for specific verbs (e.g., `create`, `delete`) or resources to ensure sufficient coverage.

        5. If existing logs are insufficient for your compliance requirements, adjust Cloud Audit Logs / Logging configuration (via organization policy, project IAM and Logging settings) to capture the required Kubernetes API activities, and document the decision that GKE control-plane manifests (including `/etc/kubernetes/manifests/kube-apiserver.yaml`) are not directly modifiable.

        6. Record the outcome of this review (evidence from `gcloud` commands, Logs Explorer screenshots/exports, and policy mapping) in your internal audit/tracking system, explicitly noting that CISGKE 2.2.1 is “Not directly configurable in GKE; covered by managed audit/logging” or documenting any residual gap and compensating controls.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify this setting because it is controlled by the GKE-managed control plane and the kube-apiserver manifest (/etc/kubernetes/manifests/kube-apiserver.yaml) is not user-editable. To address or review this finding, follow the guidance in the Manual Steps section for GKE-managed control planes.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Automation: Report API server audit policy configuration (GKE CIS 2.2.1)
        #
        # Prereqs:
        #   - Run on any machine with:
        #       * gcloud CLI configured (for GKE)
        #       * kubectl configured for the target clusters/projects
        #   - jq installed

        set -euo pipefail

        # ---- CONFIGURATION ----
        # If you want to scope this, set these before running:
        #   PROJECTS="proj-1 proj-2"
        #   CLUSTERS="cluster-1 cluster-2"
        #   REGIONS="us-central1 us-east1"
        PROJECTS="${PROJECTS:-$(gcloud projects list --format='value(projectId)')}"
        CLUSTERS="${CLUSTERS:-ALL}"
        REGIONS="${REGIONS:-ALL}"

        echo "=== GKE CIS 2.2.1 – Audit Policy Review ==="
        echo "Projects: ${PROJECTS}"
        echo "Clusters filter: ${CLUSTERS}"
        echo "Regions filter: ${REGIONS}"
        echo

        for PROJECT in $PROJECTS; do
          echo "---- Project: ${PROJECT} ----"

          # List all GKE clusters in the project
          if [[ "$REGIONS" == "ALL" ]]; then
            CLUSTER_LIST=$(gcloud container clusters list \
              --project "$PROJECT" \
              --format='value(name,location)')
          else
            CLUSTER_LIST=""
            for REGION in $REGIONS; do
              CLUSTER_LIST+=$'\n'"$(gcloud container clusters list \
                --project "$PROJECT" \
                --region "$REGION" \
                --format='value(name,location)' || true)"
            done
            CLUSTER_LIST="$(printf "%s\n" "$CLUSTER_LIST" | sed '/^$/d' | sort -u)"
          fi

          if [[ -z "$CLUSTER_LIST" ]]; then
            echo "  No clusters found."
            echo
            continue
          fi

          while read -r NAME LOCATION; do
            [[ -z "$NAME" ]] && continue

            # Optional cluster name filter
            if [[ "$CLUSTERS" != "ALL" ]]; then
              SKIP=true
              for C in $CLUSTERS; do
                if [[ "$NAME" == "$C" ]]; then
                  SKIP=false
                  break
                fi
              done
              $SKIP && continue
            fi

            echo "  Cluster: ${NAME} (${LOCATION})"

            # Describe the cluster and extract audit-related fields
            DESC_JSON=$(gcloud container clusters describe "$NAME" \
              --project "$PROJECT" \
              --location "$LOCATION" \
              --format=json)

            # For GKE, you cannot set --audit-policy-file directly, but we can check:
            # - masterAuthorizedNetworksConfig
            # - loggingService / monitoringService
            # - clusterLoggingConfig
            # The key point for this manual control: verify if API audit logs are enabled in Cloud Logging.

            LOGGING_MONITORING=$(echo "$DESC_JSON" | jq -r '
              {
                loggingService: (.loggingService // "unspecified"),
                monitoringService: (.monitoringService // "unspecified"),
                clusterLoggingConfig: (.loggingConfig.clusterConfig.enableComponents // []),
                dataplaneV2: (.dataplaneV2Config.mode // "none")
              }')

            echo "    Logging / Monitoring summary:"
            echo "$LOGGING_MONITORING" | sed 's/^/      /'

            echo "    Cloud Logging API-Server audit logs status:"
            # Check whether "APISERVER" or "ALL" logging components are enabled
            APISERVER_LOG_ENABLED=$(echo "$DESC_JSON" \
              | jq -r '
                if (.loggingConfig.clusterConfig.enableComponents // []) | index("APISERVER")
                then "enabled"
                elif (.loggingConfig.clusterConfig.enableComponents // []) | index("ALL")
                then "enabled-via-ALL"
                else "disabled-or-legacy"
                end')

            echo "      api-server audit logging (via enableComponents): ${APISERVER_LOG_ENABLED}"

            # Also check legacy loggingService
            LOGGING_SERVICE=$(echo "$DESC_JSON" | jq -r '.loggingService // "unspecified"')
            echo "      legacy loggingService: ${LOGGING_SERVICE}"

            echo
          done <<< "$CLUSTER_LIST"

          echo
        done

        cat <<'EOF'
        INTERPRETING RESULTS (MANUAL REVIEW REQUIRED)
        --------------------------------------------
        This CIS control is MARKED MANUAL and cannot be remediated by changing kube-apiserver flags in GKE.

        You must review per cluster:

        1. Look at:
             - "api-server audit logging (via enableComponents)"
             - "legacy loggingService"
           for each cluster.

        2. Potential issues that require attention:
           - api-server audit logging = "disabled-or-legacy"
             AND loggingService is not "logging.googleapis.com/kubernetes" or
             "logging.googleapis.com/kubernetes" is set but you have not configured
             Audit Logs / Kubernetes Audit Logs in Cloud Logging.
           - No organization/project-level log sinks exist that capture
             Kubernetes API Server or Admin Activity logs for this cluster.

        3. For clusters showing "disabled-or-legacy":
           - Confirm in the GCP Console -> Logging -> Logs Router and Logs Explorer
             whether Kubernetes audit / Admin Activity logs for the cluster’s master
             endpoints are being collected and retained according to your policy.

        4. For clusters with "enabled" or "enabled-via-ALL":
           - Verify that the collected logs contain the level of detail required for
             your security and compliance requirements, and that retention and
             sink targets (e.g. BigQuery, SIEM) are configured appropriately.

        There is no single automated fix; use this report to prioritize which clusters
        need deeper review and possible changes to GKE logging / Cloud Logging
        configuration to meet the intent of CIS 2.2.1.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/tasks/debug-application-cluster/audit/](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/)
