Skip to main content

Azure Enable Audit Logs - Security Rule

More Info:

Enable auditing on the Kubernetes API Server and set the desired audit log path.

Risk Level

Medium

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS AKS
  • CIS Critical Security Controls v8
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. Identify the AKS cluster and resource group

    • On any machine with Azure CLI access:
      az aks list -o table
    • Note the name (e.g., myAKSCluster) and resourceGroup (e.g., myResourceGroup) for the target cluster.
    • Confirm you are using the AKS resource group (not the MC_... node resource group).
  2. List existing diagnostic settings on the AKS resource

    • On any machine with Azure CLI access:
      az monitor diagnostic-settings list \
      --resource $(az aks show -g myResourceGroup -n myAKSCluster --query id -o tsv)
    • Review output for any diagnostic setting that includes kube-audit and kube-audit-admin under logs[].category.
  3. Verify that kube-audit and kube-audit-admin logs are enabled and flowing to a Log Analytics workspace

    • Still on a machine with Azure CLI:
      az monitor diagnostic-settings show \
      --name myAKSClusterLogs \
      --resource $(az aks show -g myResourceGroup -n myAKSCluster --query id -o tsv)
    • Confirm:
      • logs[].category contains kube-audit and kube-audit-admin.
      • Their enabled field is true.
      • workspaceId (or workspaceId-equivalent property) is present under workspaceId or workspace / logAnalyticsDestinationType, indicating “Send to Log Analytics” is configured.
  4. If audit logs are missing or disabled, configure diagnostic settings in the Azure portal

    • In the Azure portal:
      1. Open the AKS cluster’s resource group (e.g., myResourceGroup), not the MC_... group.
      2. Select your AKS cluster resource (e.g., myAKSCluster).
      3. In the left pane, choose Diagnostic settings.
      4. Click + Add diagnostic setting (or edit an existing setting).
      5. Name it (e.g., myAKSClusterLogs), select Send to Log Analytics workspace, and choose/create a workspace.
      6. Under Logs, enable at minimum kube-audit and kube-audit-admin (optionally also kube-apiserver, kube-controller-manager, kube-scheduler), then Save.
  5. Validate that new diagnostic settings are active

    • After saving in the portal, confirm via CLI:
      az monitor diagnostic-settings show \
      --name myAKSClusterLogs \
      --resource $(az aks show -g myResourceGroup -n myAKSCluster --query id -o tsv)
    • Ensure enabled: true for kube-audit and kube-audit-admin and that the Log Analytics workspace reference is present.
  6. Optionally confirm logs are being ingested in Log Analytics

    • In the Azure portal, open the selected Log Analytics workspace → Logs and run a simple query such as:
      AzureDiagnostics
      | where Category in ("kube-audit", "kube-audit-admin")
      | take 10
    • Verify that recent records are present, indicating that API server audit logs are enabled and collected.
Using kubectl

kubectl cannot be used to enable or configure API server audit logging for this finding, because it is managed as an AKS diagnostic setting in the Azure portal, not via Kubernetes API objects. To remediate, follow the Azure Portal configuration steps described in the Manual Steps section.

Automation
#!/usr/bin/env bash
# Purpose: Report AKS audit log diagnostic settings across all managed clusters in a subscription.
# Runs on: any machine with Azure CLI access to the target subscription.

set -euo pipefail

SUBSCRIPTION_ID="<PUT-SUBSCRIPTION-ID-HERE>"

# Set subscription
az account set --subscription "${SUBSCRIPTION_ID}"

echo "Listing AKS clusters and their diagnostic settings (focus: kube-audit, kube-audit-admin)..."
echo

# Get all AKS cluster resource IDs in the subscription
AKS_IDS=$(az aks list --query '[].id' -o tsv)

if [ -z "${AKS_IDS}" ]; then
echo "No AKS clusters found in subscription ${SUBSCRIPTION_ID}"
exit 0
fi

for AKS_ID in ${AKS_IDS}; do
echo "=== Cluster: ${AKS_ID} ==="

# List diagnostic settings on the managed AKS resource
DIAG_JSON=$(az monitor diagnostic-settings list \
--resource "${AKS_ID}" \
-o json)

DIAG_COUNT=$(echo "${DIAG_JSON}" | jq 'length')

if [ "${DIAG_COUNT}" -eq 0 ]; then
echo " STATUS: PROBLEM - No diagnostic settings configured on this AKS cluster."
echo " EXPECTED: At least one diagnostic setting sending kube-audit and kube-audit-admin to Log Analytics."
echo
continue
fi

# For each diagnostic setting, inspect destinations and enabled logs
echo " Found ${DIAG_COUNT} diagnostic setting(s)."
echo

echo "${DIAG_JSON}" | jq -c '.[]' | while read -r ds; do
NAME=$(echo "${ds}" | jq -r '.name')
HAS_LAW=$(echo "${ds}" | jq -r '(.workspaceId != null) or ( .logs[]? | select(.category == "kube-audit" or .category == "kube-audit-admin") | .workspaceId? != null )' 2>/dev/null || echo "false")

echo " Diagnostic setting: ${NAME}"

# Show destinations
LAW_ID=$(echo "${ds}" | jq -r '.workspaceId // empty')
if [ -n "${LAW_ID}" ]; then
echo " Destination: Log Analytics workspace: ${LAW_ID}"
else
echo " Destination: No Log Analytics workspace at root of setting (may still have per-log workspaceId)."
fi

# Show enabled logs and whether kube-audit / kube-audit-admin are on
echo " Enabled log categories:"
echo "${ds}" | jq -r '.logs[] | select(.enabled==true) | " - \(.category)"'

HAS_KUBE_AUDIT=$(echo "${ds}" | jq '[.logs[]? | select(.enabled==true and .category=="kube-audit")] | length > 0')
HAS_KUBE_AUDIT_ADMIN=$(echo "${ds}" | jq '[.logs[]? | select(.enabled==true and .category=="kube-audit-admin")] | length > 0')

if [ "${HAS_KUBE_AUDIT}" != "true" ] || [ "${HAS_KUBE_AUDIT_ADMIN}" != "true" ] || [ "${HAS_LAW}" != "true" ]; then
echo " STATUS: PROBLEM"
echo " - kube-audit enabled: ${HAS_KUBE_AUDIT}"
echo " - kube-audit-admin enabled: ${HAS_KUBE_AUDIT_ADMIN}"
echo " - Sent to Log Analytics: ${HAS_LAW}"
echo " EXPECTED: kube-audit and kube-audit-admin enabled and sent to at least one Log Analytics workspace."
else
echo " STATUS: OK (kube-audit and kube-audit-admin enabled and sent to Log Analytics)."
fi

echo
done

echo
done

How to interpret output

  • Problem / non-compliant:

    • Cluster shows: STATUS: PROBLEM - No diagnostic settings configured on this AKS cluster.
    • Or any diagnostic setting shows:
      • kube-audit enabled: false or
      • kube-audit-admin enabled: false or
      • Sent to Log Analytics: false.
  • Compliant (per benchmark intent):

    • At least one diagnostic setting for the AKS cluster reports:
      • STATUS: OK (kube-audit and kube-audit-admin enabled and sent to Log Analytics).

Additional Reading: