Skip to content

Dieses Tool ist nicht mit The Linux Foundation, der Cloud Native Computing Foundation (CNCF) oder dem Kubernetes-Projekt verbunden und wird von diesen weder befürwortet noch gesponsert. Kubernetes und K8s sind eingetragene Marken von The Linux Foundation. EKS, GKE, AKS und andere Namen sind Marken ihrer jeweiligen Inhaber.

Kubernetes-Audit-Policy: was Sie für Forensik loggen sollten

Eine Kubernetes-Audit-Policy, die Beweise für Untersuchungen erfasst (exec, RBAC, Workloads, Tokens), ohne Secrets zu loggen oder im Rauschen zu versinken.

Veröffentlicht am 5 Min. Lesezeit

TL;DR. Eine Audit-Policy ist eine geordnete Liste von Regeln; die erste passende legt das Audit-Level jedes Requests fest. Für die Forensik brauchen Sie Metadata für alles, Request oder RequestResponse für Schreibzugriffe auf RBAC-Objekte, Pods und Workload-Controller, Request für pods/exec, pods/attach, pods/portforward, nodes/proxy und serviceaccounts/token, und strikt Metadata für Secrets, ConfigMaps und Token-Reviews. Lassen Sie Health-Checks und das Grundrauschen von Kubelets und kube-proxy weg. Leiten Sie das Ergebnis aus dem Cluster heraus und bewahren Sie es mindestens 90 Tage auf.

Ein selbst betriebener API-Server schreibt nichts, solange Sie ihm keine Policy geben: Die Kubernetes-Dokumentation zum Auditing sagt klar, dass ohne --audit-policy-file keine Events protokolliert werden. Auf EKS, GKE und AKS legt der Anbieter die Policy fest, und Ihre einzige Wahl ist, welche Logs Sie exportieren (siehe den Export-Leitfaden für EKS, GKE und AKS). So oder so: Wer weiß, wie eine gute Policy aussieht, weiß, welche Beweise er erwarten kann.

Wie Regeln ausgewertet werden

Jede Regel kann auf users, userGroups, verbs, resources (mit API-Gruppe und optional resourceNames), namespaces und nonResourceURLs matchen. Regeln werden der Reihe nach verarbeitet, die erste passende gewinnt. Ein Request, auf den keine Regel passt, wird nicht protokolliert. Zwei praktische Folgen:

  • Stellen Sie Ausschlüsse (level: None) und Ihre „niemals Bodies loggen“-Regeln vor die breiten Regeln.
  • Enden Sie mit einem allgemeinen level: Metadata, damit nichts stillschweigend durchfällt.

omitStages entfernt Stages global oder pro Regel. Fast alle lassen RequestReceived weg, das das finale Event dupliziert. omitManagedFields: true entfernt das sperrige metadata.managedFields aus protokollierten Bodies.

Was Ermittler brauchen und warum

BeweisMindest-LevelWarum
Wer hat was aufgerufen, von wo, mit welchem ErgebnisMetadata für allesIdentität, Quell-IP, Verb, Objekt, Code: das Rückgrat jeder Timeline
Pod- und Workload-Specs (pods, deployments, daemonsets, statefulsets, jobs, cronjobs) bei create / update / patchRequestOhne Body sehen Sie weder privileged, hostPID, einen hostPath noch das Image
RBAC-Schreibzugriffe (roles, rolebindings, clusterroles, clusterrolebindings)Request oder RequestResponseroleRef und subjects zeigen, ob ein Binding cluster-admin gewährt und wem
pods/exec, pods/attach, pods/portforward, nodes/proxyMetadata genügt, Request passtDer Befehl steht in requestURI; die Session selbst wird nie aufgezeichnet
serviceaccounts/tokenRequest, nicht RequestResponseDer Request zeigt angefragte Laufzeit und Audience; die Response enthält das Token selbst
secrets, configmaps, tokenreviewsNur MetadataDie Bodies enthalten Zugangsdaten; sie zu loggen macht das Audit-Log zum Credential-Speicher
Löschen von eventsMetadataEvents zu löschen ist ein billiger Anti-Forensik-Schritt

Eine forensisch ausgerichtete Policy

Diese Policy ist ein Ausgangspunkt, keine Copy-and-paste-Lösung. Testen Sie sie auf einem Nicht-Produktionscluster und beobachten Sie das Log-Volumen.

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
  - "RequestReceived"
omitManagedFields: true
rules:
  # 1. Noise: health checks and high-frequency system reads
  - level: None
    nonResourceURLs: ["/healthz*", "/livez*", "/readyz*", "/version"]
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
      - group: ""
        resources: ["endpoints", "services", "services/status"]
  - level: None
    userGroups: ["system:nodes"]
    verbs: ["get"]
    resources:
      - group: ""
        resources: ["nodes", "nodes/status"]

  # 2. Credentials: never log bodies
  - level: Metadata
    resources:
      - group: ""
        resources: ["secrets", "configmaps"]
      - group: "authentication.k8s.io"
        resources: ["tokenreviews"]

  # 3. Interactive access and token minting (request only: the
  #    TokenRequest response contains the token)
  - level: Request
    resources:
      - group: ""
        resources: ["pods/exec", "pods/attach", "pods/portforward",
                    "nodes/proxy", "serviceaccounts/token"]

  # 4. Events: keep deletions, drop the rest
  - level: Metadata
    verbs: ["delete", "deletecollection"]
    resources:
      - group: ""
        resources: ["events"]
      - group: "events.k8s.io"
        resources: ["events"]
  - level: None
    resources:
      - group: ""
        resources: ["events"]
      - group: "events.k8s.io"
        resources: ["events"]

  # 5. Writes to workloads, RBAC, service accounts, admission: full bodies
  - level: RequestResponse
    verbs: ["create", "update", "patch", "delete", "deletecollection"]
    resources:
      - group: ""
        resources: ["pods", "serviceaccounts", "namespaces", "nodes"]
      - group: "apps"
      - group: "batch"
      - group: "rbac.authorization.k8s.io"
      - group: "admissionregistration.k8s.io"

  # 6. Everything else
  - level: Metadata

Einige Entscheidungen zur Erklärung:

  • Regel 2 vor Regel 5. Secrets müssen auch bei create und update auf Metadata bleiben, also muss die Secrets-Regel zuerst greifen.
  • Regel 3 nutzt Request. Streaming-Subressourcen haben keinen aussagekräftigen Body; was Sie brauchen (Befehl, Container), steht in der URI. Für serviceaccounts/token würde RequestResponse ein gültiges Bearer-Token protokollieren.
  • Status-Updates der Kubelets (Patches auf nodes/status, pods/status) fallen in Regel 6 auf Metadata. Das reicht für Untersuchungen völlig und ist viel günstiger als Bodies.
  • Lesezugriffe bleiben auf Metadata. Response-Bodies von list-Aufrufen zu loggen lässt Audit-Logs explodieren und hilft einer Untersuchung selten.

Zum Vergleich: Die Policy, die AWS im EKS Best Practices Guide veröffentlicht, folgt derselben Struktur: Metadata für Secrets, ConfigMaps und Token-Reviews, Request für serviceaccounts/token, volle Bodies für die meisten bekannten API-Gruppen. Ein wichtiger Unterschied: Sie verwirft events vollständig, gelöschte Events sind auf EKS also nicht sichtbar.

Aktivierung auf einem selbst betriebenen API-Server

Auf einer Control Plane im kubeadm-Stil läuft der API-Server als statischer Pod. Ergänzen Sie die Flags in /etc/kubernetes/manifests/kube-apiserver.yaml und mounten Sie Policy und Log-Verzeichnis:

- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit/audit.log
- --audit-log-maxage=30
- --audit-log-maxbackup=10
- --audit-log-maxsize=100

maxage ist in Tagen, maxsize in Megabyte angegeben. Das Kubelet startet den API-Server neu, wenn sich das Manifest ändert. Distributionen wie k3s und RKE2 stellen dieselben Flags über ihre eigene Konfiguration bereit; die genauen Schlüssel finden Sie in deren Dokumentation.

Die Dokumentation weist außerdem darauf hin, dass Auditing den Speicherverbrauch des API-Servers erhöht, abhängig davon, was Sie loggen. Ein weiterer Grund, Bodies auf die relevanten Schreibzugriffe zu beschränken.

Logs von der Maschine holen

Ein Angreifer mit cluster-admin und einem privilegierten Pod kann Dateien auf Control-Plane-Nodes lesen und ändern. Logs, die nur dort existieren, kontrolliert der Angreifer. Zwei Optionen:

  • Das Webhook-Backend (--audit-webhook-config-file) sendet Batches an einen HTTP-Endpunkt: einen Log-Collector, ein SIEM, eine Queue.
  • Das Log-Backend plus Shipper (Fluent Bit, Vector, der Cloud-Agent) liest audit.log mit und schickt es in einen zentralen Speicher.

Auch der Kubernetes Hardening Guide von NSA und CISA empfiehlt, Audit-Logging zu aktivieren und die Logs außerhalb des Clusters zu speichern. Bewahren Sie mindestens 90 Tage auf: Der Erstzugriff liegt oft Wochen vor der Erkennung.

Die Policy an echten Erkennungen prüfen

Ein guter Test: Spielen Sie auf einem Labor-Cluster eine bekannte bösartige Sequenz durch (exec in einen Pod, einen privilegierten Pod mit hostPath auf / anlegen, einen Service Account an cluster-admin binden), exportieren Sie das Log und ziehen Sie es in den Audit-Log-Analyzer. Erscheinen die Findings zu privilegiertem Pod oder cluster-admin nicht, werden die entsprechenden Bodies nicht protokolliert. Der Referenzteil des Analyzers listet die Erkennungen; die Schritt-für-Schritt-Anleitung erklärt, wie Sie das Ergebnis lesen.

Verwandte Artikel

Verwandte Artikel

Die blinden Flecken von Kubernetes-Audit-Logs: Aktivität in Containern, Zugriffe auf Kubelet und etcd, Policy-Lücken, fälschbare Felder und was sie schließt.
Das Kubernetes-Audit-Log-Format Feld für Feld: Stages, Level, user, sourceIPs, objectRef, responseStatus, Annotationen und was davon in der Forensik zählt.
Ein fiktiver Kubernetes-Incident im Audit-Log: exponiertes Dashboard-Token, can-i-Aufklärung, Secret-Diebstahl, privilegiertes DaemonSet, XMRig-CronJob.

Dieses Tool ist nicht mit The Linux Foundation, der Cloud Native Computing Foundation (CNCF) oder dem Kubernetes-Projekt verbunden und wird von diesen weder befürwortet noch gesponsert. Kubernetes und K8s sind eingetragene Marken von The Linux Foundation. EKS, GKE, AKS und andere Namen sind Marken ihrer jeweiligen Inhaber.