How to Export Kubernetes Audit Logs

How to Export Kubernetes Audit Logs

SOC Prime Team
SOC Prime Team linkedin icon Follow

Where Kubernetes audit logs live depends on who runs your control plane. On a self-managed cluster, they’re a JSON-lines file on the control plane node, at whatever path –audit-log-path points to. On EKS, they go to CloudWatch Logs, on AKS to a Log Analytics workspace or storage account, and on GKE to Cloud Audit Logs. One thing holds everywhere: audit logging has to be switched on. On self-managed clusters and EKS it’s off until someone enables it.

The audit log records every request to the Kubernetes API: who ran kubectl exec into which pod, who read which secret, who bound themselves to cluster-admin. Prime Core has 93 detection rules for Kubernetes audit data, mapped to 220 MITRE ATT&CK techniques. Among them: exec into running containers (T1609), deploying rogue containers (T1610) and reading credentials through the container API (T1552.007).

Get Started for Free

Before you start

Is it enabled?

PlatformWhere to check
Self-managed (kubeadm and similar)–audit-policy-file and –audit-log-path on the API server; with kubeadm, in /etc/kubernetes/manifests/kube-apiserver.yaml
EKSCluster → Observability → control plane logging, “audit” log type
AKSDiagnostic settings on the cluster, categories kube-audit or kube-audit-admin
GKEOn by default for Admin Activity; Data Access logging for Kubernetes is opt-in

If it wasn’t on, there’s nothing to export for the past, and the rest of this guide is about next time.

Detail depends on the policy. At Metadata level you see who did what to which object. At Request or RequestResponse level you also see the bodies, for example the pod spec that asked for privileged: true. Know which one you have before you go looking.

Expect volume. Controllers and service accounts talk to the API constantly. On AKS, kube-audit-admin leaves out read-only get and list calls, which keeps size sane but also hides secret reads.

Export it

Self-managed cluster, on a control plane node:

# confirm the path first

sudo grep -- '--audit-log-path' /etc/kubernetes/manifests/kube-apiserver.yaml


sudo cat /var/log/kubernetes/audit/audit.log > k8s_audit.jsonl

Rotated files (from –audit-log-maxbackup) sit next to it with a timestamp in the name. Include them if the window reaches back.

EKS, from CloudWatch Logs:

aws logs filter-log-events --log-group-name /aws/eks/my-cluster/cluster \

  --log-stream-name-prefix kube-apiserver-audit \

  --start-time $(date -d '2026-10-19T00:00:00Z' +%s000) --end-time $(date -d '2026-10-20T00:00:00Z' +%s000) \

  --output json | jq -c '.events[].message | fromjson' > eks_audit_1019.jsonl

Each CloudWatch event wraps the audit entry as a string; fromjson unwraps it. The date -d syntax is GNU; on macOS, compute the millisecond timestamps another way.

AKS, from Log Analytics (resource-specific tables):

az monitor log-analytics query -w <workspace-id> \

  --analytics-query "AKSAuditAdmin | where TimeGenerated between (datetime(2026-10-19) .. datetime(2026-10-20))" \

  --output json > aks_audit_1019.json

GKE, from Cloud Audit Logs:

gcloud logging read 'resource.type="k8s_cluster" AND logName:"cloudaudit.googleapis.com" AND timestamp>="2026-10-19T00:00:00Z" AND timestamp<"2026-10-20T00:00:00Z"' \

  --project=my-project --format=json | jq -c '.[]' > gke_audit_1019.jsonl

What to look for

RequestWhy it matters
create on pods/exec (objectRef.subresource: exec)Someone opened a shell inside a running container
create of a ClusterRoleBinding to cluster-adminPrivilege escalation to full control
get or list on secrets by an unusual identityCredential harvesting
Pods created with privileged, hostPath or hostNetworkA step toward escaping onto the node
user.username: system:anonymous with a 2xx responseAnonymous access that shouldn’t work
Bursts of 403 from one service accountA stolen token feeling out its permissions

Upload, sanitize and review in LogTotal

  1. Upload. Open logtotal.com and drop in the .jsonl file.
  2. Sanitize. [what gets masked: usernames, service account names, source IPs, namespaces, object names]. Look it over before you continue.
  3. Review.

When it goes wrong

SymptomLikely causeFix
No audit file on the control planeAPI server has no audit policy configuredExpected; configure it for the future
EKS log group or audit streams missingThe “audit” control plane log type isn’t enabledEnable it for the future
Each line is one long escaped stringCloudWatch wrappingUnwrap with fromjson, as above
You can see who changed a pod, but not howPolicy is at Metadata levelRaise the level for sensitive resources
No secret reads in AKS datakube-audit-admin excludes get and listCollect kube-audit if you need them

FAQ

Aren’t container logs enough?

No. Container logs show what an application printed. The audit log shows what people and service accounts did to the cluster. Different questions, different logs.

Can I read the audit file on a managed cluster?

No. On EKS, AKS and GKE, you don’t get access to the control plane nodes. The provider’s logging service is the only route.

Join SOC Prime's Detection as Code platform to improve visibility into threats most relevant to your business. To help you get started and drive immediate value, book a meeting now with SOC Prime experts.