Skip to main content

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

Remediation

Manual Steps
  1. On any machine with gcloud and project access, list clusters and identify the affected one:

    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:

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

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.

Automation
#!/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

Additional Reading: