#!/usr/bin/env bash
#
# audit-api-audit-logging.sh
#
# Purpose:
# Gather evidence about Kubernetes API audit logging and whether
# audit logs are being shipped off-cluster, for manual review.
#
# Run on:
# Any machine with:
# - kubectl configured for the cluster
# - access to cloud CLI (optional but recommended: aws / az / gcloud / oci)
#
# Usage:
# chmod +x audit-api-audit-logging.sh
# ./audit-api-audit-logging.sh > audit-api-audit-logging-$(date +%F).txt
set -euo pipefail
echo "=== Audit: Kubernetes API Audit Logging & Off-Cluster Shipping ==="
echo "Timestamp: $(date -Iseconds)"
echo
echo "Cluster info (for context)"
echo "------------------------------------------------------------"
kubectl version --short 2>/dev/null || echo "kubectl version: unable to query (check kubeconfig)"
echo
kubectl cluster-info 2>/dev/null || echo "kubectl cluster-info: unable to query (check permissions)"
echo
###############################################################################
# 1. Managed-control-plane detection (best-effort, for operator context)
###############################################################################
echo "Control plane type detection (best effort)"
echo "------------------------------------------------------------"
# Try common hints but do NOT assume result is authoritative.
PROVIDER_HINT="unknown"
if kubectl get ns kube-system >/dev/null 2>&1; then
if kubectl get configmap -n kube-system aws-auth >/dev/null 2>&1; then
PROVIDER_HINT="EKS"
elif kubectl get nodes -o jsonpath='{.items[0].metadata.labels.eks\.amazonaws\.com/nodegroup}' >/dev/null 2>&1; then
PROVIDER_HINT="EKS"
elif kubectl get nodes -o jsonpath='{.items[0].metadata.labels.cloud\.google\.com/gke-nodepool}' >/dev/null 2>&1; then
PROVIDER_HINT="GKE"
elif kubectl get nodes -o jsonpath='{.items[0].metadata.labels.agentpool}' >/dev/null 2>&1; then
PROVIDER_HINT="AKS"
fi
fi
echo "Provider hint (heuristic, verify manually): ${PROVIDER_HINT}"
echo
###############################################################################
# 2. In-cluster evidence of API audit logging usage
###############################################################################
echo "In-cluster evidence related to API audit logging"
echo "------------------------------------------------------------"
echo
echo "2.1. Check for namespaces and components commonly used for log shipping"
echo "-----------------------------------------------------------------"
kubectl get ns 2>/dev/null | sed 's/^/ /' || echo " Unable to list namespaces"
echo
echo "2.2. Check for logging / audit shipping DaemonSets (cluster-wide)"
echo "-----------------------------------------------------------------"
kubectl get daemonset -A 2>/dev/null | sed 's/^/ /' || echo " Unable to list DaemonSets"
echo
echo "2.3. Check for logging / audit shipping Deployments (cluster-wide)"
echo "-----------------------------------------------------------------"
kubectl get deploy -A 2>/dev/null | sed 's/^/ /' || echo " Unable to list Deployments"
echo
echo "2.4. Look for components suggesting API server audit ingestion"
echo "-----------------------------------------------------------------"
echo " (grep for 'audit' in Deployments/DaemonSets names)"
{
kubectl get deploy -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name --no-headers 2>/dev/null
kubectl get daemonset -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name --no-headers 2>/dev/null
} | grep -i "audit" || echo " No Deployments/DaemonSets with 'audit' in the name found (this may be OK)."
###############################################################################
# 3. Provider-specific hints (manual review required)
###############################################################################
# NOTE:
# For managed control planes, *enabling API audit logging and off-cluster
# shipping* is configured in the cloud provider console / API / IaC.
# The following commands only help you discover current logging-related
# config; they do not guarantee that audit logging is properly enabled.
###############################################################################
echo
echo "Provider-specific evidence (you must review & interpret manually)"
echo "------------------------------------------------------------"
case "${PROVIDER_HINT}" in
"EKS")
echo "Detected EKS (heuristic)."
echo
echo "3.1. List EKS clusters and logging configuration via AWS CLI"
echo " (Run these on a machine with 'aws' configured and proper IAM perms)"
cat <<'EOF'
# List clusters
aws eks list-clusters
# For each cluster, show enabled control-plane logs, including audit
aws eks describe-cluster \
--name <CLUSTER_NAME> \
--query 'cluster.logging.clusterLogging[*].{types:types, enabled:enabled}'
EOF
echo
echo "Interpretation (problem indicators):"
echo " - If 'audit' is NOT present in 'types' with 'enabled: true',"
echo " then API audit logging is not enabled for that EKS cluster."
echo " - Even when enabled, confirm that CloudWatch Logs or another"
echo " external, tamper-resistant destination retains logs according"
echo " to your policy (verify in AWS console/IaC)."
;;
"GKE")
echo "Detected GKE (heuristic)."
echo
echo "3.1. List GKE clusters and logging config via gcloud"
echo " (Run these on a machine with 'gcloud' configured and proper perms)"
cat <<'EOF'
# List clusters with logging details
gcloud container clusters list \
--format="table(name,location,loggingService,loggingConfig)"
# For a specific cluster, get full logging config (includes audit logs)
gcloud container clusters describe <CLUSTER_NAME> \
--region <REGION> \
--format="yaml(loggingConfig,loggingService)"
EOF
echo
echo "Interpretation (problem indicators):"
echo " - If 'loggingService' is 'none', control-plane logs (including audit)"
echo " are not being exported."
echo " - If 'loggingConfig.componentConfig.enableComponents' does NOT include"
echo " 'APISERVER', then API server logs (including audits) may not be"
echo " collected."
echo " - Confirm logs are sent to Cloud Logging with retention and access"
echo " controls that make them tamper-resistant."
;;
"AKS")
echo "Detected AKS (heuristic)."
echo
echo "3.1. List AKS clusters and diagnostic settings via Azure CLI"
echo " (Run these on a machine with 'az' configured and proper perms)"
cat <<'EOF'
# List AKS clusters
az aks list -o table
# For a given cluster, show diagnostic settings on the managed resource
AKS_RG="<RESOURCE_GROUP>"
AKS_NAME="<CLUSTER_NAME>"
# Get the underlying managed resource id
AKS_ID=$(az aks show -g "$AKS_RG" -n "$AKS_NAME" --query id -o tsv)
# List diagnostic settings (includes control-plane / audit categories if enabled)
az monitor diagnostic-settings list --resource "$AKS_ID" -o json
EOF
echo
echo "Interpretation (problem indicators):"
echo " - If there are NO diagnostic settings for the AKS resource, audit"
echo " logs are not being shipped off-cluster."
echo " - In the diagnostic settings JSON, if categories like 'kube-audit'"
echo " or equivalent are absent or disabled, API audit logging is not"
echo " being exported."
echo " - Confirm destination is Log Analytics / Event Hub / storage with"
echo " appropriate tamper-resistance and retention."
;;
*)
echo "Provider unknown from heuristics."
echo
echo "3.1. MANUAL: Determine your control-plane provider and review:"
echo " - Platform documentation for 'Kubernetes API audit logging'"
echo " - Control-plane logging / diagnostics settings in the provider console"
echo " - IaC definitions (Terraform, CloudFormation, ARM/Bicep, etc.)"
echo
echo "Example manual evidence commands (generic; adjust for your platform):"
cat <<'EOF'
# If using Terraform:
grep -Rni "audit" . | head
# If using Helm or other IaC for logging stacks:
grep -Rni "audit" logging/ manifests/ | head
EOF
;;
esac
###############################################################################
# 4. What output indicates a problem?
###############################################################################
echo
echo "Interpretation summary: what indicates a potential PROBLEM"
echo "------------------------------------------------------------"
cat <<'EOF'
Flag as needing remediation if you observe ANY of the following:
1) EKS:
- In 'aws eks describe-cluster ...':
- 'audit' is missing from 'cluster.logging.clusterLogging[*].types'
OR
- 'audit' exists but 'enabled' is false.
- No clear CloudWatch Logs / external destination configured for control-plane logs.
2) GKE:
- 'loggingService' is 'none' for the cluster.
- 'loggingConfig.componentConfig.enableComponents' does NOT include 'APISERVER'.
- Logs are not visible in Cloud Logging or retention is too short / not protected.
3) AKS:
- 'az monitor diagnostic-settings list --resource <AKS_ID>' returns no settings.
- Diagnostic settings do not include categories for API server / audit logs
(e.g., 'kube-audit' or equivalent).
- Destination (Log Analytics, Event Hub, Storage) is missing or clearly
not tamper-resistant.
4) Any provider:
- No evidence that API-level audit logs are being produced by the control plane.
- No evidence that such logs are being shipped to an external, independent,
tamper-resistant log store.
- IaC / configuration does not define audit logging or external log sinks.
NOTE:
This script only gathers evidence; it does NOT and CANNOT fully
determine compliance automatically. You must review the outputs
and your provider's configuration to decide if:
- Kubernetes API audit logging is enabled, AND
- Audit logs are being forwarded to an external, tamper-resistant store.
EOF
echo
echo "=== End of audit ==="