Eine übersichtliche Referenz der Architekturmuster, die in der CKS-Prüfung getestet werden. Von oben nach unten lesen oder zu einem Abschnitt springen.
Clustereinrichtung
Bewerten Sie die Cluster-Konfiguration anhand branchenüblicher Sicherheitspraktiken.
Verwenden Sie `kube-bench`, um CIS Kubernetes Benchmark-Prüfungen für die Steuerungsebene und Worker-Knoten durchzuführen.
Warum: `kube-bench` ist das Standardwerkzeug für diese spezielle Aufgabe und automatisiert Prüfungen anhand umfassender CIS-Richtlinien.
Erzwingen Sie eine starke Authentifizierung für alle Anfragen an den API-Server.
Setzen Sie die `kube-apiserver`-Flags: `--anonymous-auth=false`, um nicht authentifizierte Anfragen abzulehnen, und `--client-ca-file`, um die Validierung von Client-Zertifikaten (mTLS) zu erzwingen.
Warum: Diese Flags sind grundlegende Kontrollen, um anonymen Zugriff zu eliminieren und authentifizierte, verschlüsselte Kommunikation mit dem API-Server zu erzwingen.
Sichern Sie den etcd-Zustandsspeicher des Clusters vor unbefugtem Zugriff und Datendiebstahl.
Konfigurieren Sie etcd mit mTLS für die gesamte Client- und Peer-Kommunikation (`--cert-file`, `--key-file`, `--peer-cert-file`). Aktivieren Sie die Ruhezustandsverschlüsselung von Secrets über das `--encryption-provider-config`-Flag des API-Servers.
Warum: etcd enthält alle Cluster-Secrets. Die Verschlüsselung von Daten während der Übertragung (mTLS) und im Ruhezustand ist entscheidend, um sensible Informationen zu schützen, selbst wenn etcd-Knoten kompromittiert werden.
Rotieren Sie etcd-Verschlüsselungsschlüssel im Ruhezustand ohne Ausfallzeiten.
1. Fügen Sie den neuen Schlüssel als ersten Eintrag in die `EncryptionConfiguration`-Datei ein. 2. Starten Sie alle API-Server neu. 3. Erzwingen Sie die erneute Verschlüsselung aller Secrets (`kubectl get secrets -A -o json | kubectl replace -f -`). 4. Entfernen Sie nach der Überprüfung den alten Schlüssel aus der Konfiguration und starten Sie die API-Server erneut.
Warum: Eine Änderung der Konfiguration wirkt sich nur auf neue Schreibvorgänge aus. Vorhandene Daten müssen neu geschrieben werden, um mit dem neuen Schlüssel verschlüsselt zu werden. Das vorzeitige Entfernen des alten Schlüssels führt zum Datenverlust.
Implementieren Sie ein Zero-Trust-Netzwerkmodell innerhalb eines Namespaces.
Wenden Sie eine `NetworkPolicy` mit einem leeren `podSelector: {}` und `policyTypes: [Ingress, Egress]` an, jedoch ohne `ingress`- oder `egress`-Regeln. Dies wählt alle Pods aus und verweigert den gesamten Datenverkehr.
Warum: Diese Richtlinie etabliert eine "Alles verweigern"-Baseline und erzwingt explizite "Erlauben"-Regeln für alle erforderlichen Kommunikationen, was die Grundlage von Zero-Trust-Netzwerken ist.
Egress NetworkPolicies blockieren die DNS-Auflösung für Pods.
Fügen Sie eine spezifische Egress-Regel hinzu, um den Datenverkehr zum Cluster-DNS-Dienst zu erlauben. Erlauben Sie Egress zu Port 53 über UDP- und TCP-Protokolle. Wählen Sie die kube-dns-Pods über `namespaceSelector` und `podSelector` aus, falls möglich.
Warum: NetworkPolicies sind granular. Eine allgemeine Egress-Regel für einen IP-Block deckt möglicherweise nicht das spezifische Protokoll (UDP) ab, das für DNS erforderlich ist, was zu Auflösungsfehlern führt.
Sichern Sie den externen Zugriff auf Dienste, die über einen Ingress bereitgestellt werden.
Konfigurieren Sie die Ingress-Ressource, indem Sie einen `tls`-Abschnitt hinzufügen, der auf ein Kubernetes Secret vom Typ `kubernetes.io/tls` verweist. Das Secret muss das TLS-Zertifikat und den privaten Schlüssel enthalten.
Warum: Dies zentralisiert die TLS-Terminierung am Ingress-Controller, verschlüsselt den Datenverkehr von Clients zur Clustergrenze und vereinfacht die Zertifikatsverwaltung für Backend-Dienste.
Cluster-Härtung
Gewähren Sie Benutzern oder Anwendungen nur die minimal erforderlichen Berechtigungen.
Verwenden Sie nach Möglichkeit `Roles` und `RoleBindings` im Namespace-Bereich. Vermeiden Sie `cluster-admin` und Wildcards (`"*"`) in `verbs` oder `resources`. Gewähren Sie spezifische Berechtigungen wie `["get", "list"]` für `["pods"]`.
Warum: Dies minimiert den Schadenbereich, falls ein Konto oder Token kompromittiert wird, und verhindert laterale Bewegungen und Privilegienerweiterungen.
Reduzieren Sie die Angriffsfläche für Pods, die nicht mit der Kubernetes-API interagieren müssen.
Deaktivieren Sie das automatische Mounten von Service-Account-Tokens, indem Sie `automountServiceAccountToken: false` im ServiceAccount oder in der Pod-Spezifikation setzen.
Warum: Wenn ein Pod kompromittiert wird, kann ein Angreifer ein gemountetes Token nicht nutzen, um auf den API-Server zuzugreifen, wodurch Cluster-Angriffe, die vom kompromittierten Pod ausgehen, verhindert werden.
Überprüfen Sie, ob ein bestimmter Benutzer oder Dienstkonto die Berechtigung hat, eine Aktion auszuführen.
Verwenden Sie `kubectl auth can-i <verb> <resource> --as=<user>` oder `kubectl auth can-i <verb> <resource> --as=system:serviceaccount:<ns>:<sa-name>`.
Warum: Dieser Befehl ermöglicht die Identitätsübernahme, um effektive Berechtigungen genau zu überprüfen, ohne alle Roles und Bindings manuell parsen zu müssen.
Wahren Sie die Clustersicherheit durch regelmäßige Rotation der Zertifikate von Control Plane und Kubelet.
Für kubeadm-Cluster verwenden Sie `kubeadm certs renew all`. Für andere folgen Sie dem dokumentierten manuellen oder automatisierten Rotationsverfahren. Aktivieren Sie die Rotation der kubelet Client/Server-Zertifikate über dessen Konfiguration.
Warum: Regelmäßige Rotation begrenzt das Zeitfenster, in dem ein Angreifer ein kompromittiertes Zertifikat verwenden kann. Es ist eine kritische Sicherheitshygiene-Praxis.
Ein Worker-Knoten wird verdächtigt, kompromittiert zu sein und muss sofort isoliert werden.
Verwenden Sie zuerst `kubectl cordon <node-name>`, um zu verhindern, dass neue Pods geplant werden. Verwenden Sie dann `kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data`, um laufende Workloads sicher zu entfernen.
Warum: Das Cordoning und Draining ist das Standardverfahren, um einen Knoten nicht-destruktiv außer Betrieb zu nehmen. Es ermöglicht die Umplanung von Workloads an anderer Stelle, während der kompromittierte Knoten für forensische Analysen erhalten bleibt.
Systemhärtung
Beschränken Sie die Systemaufrufe, die ein Container an den Host-Kernel richten kann.
Im Pod- oder Container-`securityContext` setzen Sie `seccompProfile.type` auf `RuntimeDefault` für eine sichere Basislinie oder auf `Localhost` mit einem Pfad zu einem benutzerdefinierten JSON-Profil für strengere Kontrolle.
Warum: Seccomp reduziert die Angriffsfläche des Kernels innerhalb eines Containers und verhindert Exploits gegen Kernel-Schwachstellen, indem es ungenutzte oder gefährliche Systemaufrufe blockiert.
Beschränken Sie Container-Prozesse, indem Sie den Zugriff auf Dateien, Netzwerkfähigkeiten und andere Ressourcen einschränken.
Wenden Sie ein AppArmor-Profil auf einen Container über die Annotation an: `container.apparmor.security.beta.kubernetes.io/<container_name>: localhost/<profile_name>`. Das Profil muss auf dem Knoten vorab geladen sein.
Warum: AppArmor bietet Mandatory Access Control (MAC) und fügt eine entscheidende Schicht zur Verteidigung in der Tiefe hinzu, um eine kompromittierte Anwendung einzudämmen und den Zugriff auf unautorisierte Ressourcen zu verhindern.
Ein Container benötigt eine spezifische privilegierte Operation (z. B. Binden an Port 80), ohne als Root zu laufen.
Im `securityContext.capabilities`, `drop: ["ALL"]` und dann `add: ["NET_BIND_SERVICE"]`.
Warum: Dies folgt dem Prinzip der geringsten Rechte, indem nur die spezifische erforderliche Linux-Capability gewährt wird, wodurch die umfassenden Berechtigungen des Root-Benutzers vermieden werden.
Verhindern Sie, dass ein Container vollen Zugriff auf das Hostsystem erhält.
Setzen Sie `securityContext.privileged: false` (was der Standard ist). Verwenden Sie Pod Security Standards oder OPA/Kyverno, um dies clusterweit durchzusetzen.
Warum: Ein privilegierter Container verfügt über nahezu alle Host-Fähigkeiten und Gerätezugriffe, wodurch die Container-Isolation effektiv deaktiviert wird. Es ist ein primärer Vektor für Container-Escape.
Minimierung von Microservice-Schwachstellen
Erzwingen Sie grundlegende oder strikte Sicherheitskonfigurationen für Pods auf Namespace-Ebene.
Wenden Sie Labels auf den Namespace an, z. B. `pod-security.kubernetes.io/enforce: restricted`. Die Modi sind `enforce`, `audit` und `warn`.
Warum: Pod Security Standards (PSS) bieten eine integrierte, mehrstufige Sicherheitsrichtlinie, die die veraltete PodSecurityPolicy ersetzt und die Durchsetzung von Sicherheitspraktiken erleichtert.
Härten Sie einen Pod, indem Sie mehrere Sicherheitskontrollen gleichzeitig anwenden.
Konfigurieren Sie einen `securityContext`, der `runAsNonRoot: true`, `allowPrivilegeEscalation: false` und `readOnlyRootFilesystem: true` kombiniert.
Warum: Dieser Defense-in-Depth-Ansatz schichtet mehrere Schutzmaßnahmen: Verhinderung der Root-Ausführung, Blockierung von Privilegieneskalationsvektoren (wie setuid) und Unveränderbarkeit des Container-Dateisystems.
Führen Sie nicht vertrauenswürdige oder Multi-Tenant-Workloads mit stärkerer Isolation als Standardcontainer aus.
Definieren Sie eine `RuntimeClass`-Ressource, die auf einen Sandboxed-Runtime-Handler (z. B. gVisor, Kata Containers) verweist. Weisen Sie Pods mithilfe von `spec.runtimeClassName` zu.
Warum: Sandboxed-Runtimes verwenden einen User-Space-Kernel oder leichtgewichtige VMs, um Systemaufrufe abzufangen, wodurch eine zusätzliche Isolationsschicht zwischen dem Container und dem Host-Kernel bereitgestellt wird.
Erzwingen Sie komplexe, benutzerdefinierte Sicherheitsrichtlinien, die nicht von den Standard-Kubernetes-Kontrollen abgedeckt werden.
Stellen Sie OPA Gatekeeper bereit. Definieren Sie Richtlinien mithilfe von `ConstraintTemplate` (der Rego-Logik) und wenden Sie diese mit `Constraint`-Ressourcen an.
Warum: Gatekeeper fungiert als validierender Admission-Webhook, der es Ihnen ermöglicht, beliebige Regeln durchzusetzen, wie das Erfordernis spezifischer Labels, das Verbieten von Host-Pfaden oder das Erzwingen von Ressourcenlimits.
Stellen Sie Secrets Pods auf die sicherste Weise zur Verfügung.
Mounten Sie Secrets als Dateien in ein Volume. Für noch größere Sicherheit verwenden Sie einen Secrets-Store-CSI-Treiber, um Secrets aus einem externen Tresor (z. B. HashiCorp Vault, AWS Secrets Manager) direkt in den Pod zu mounten.
Warum: Das Mounten als Dateien ist sicherer als Umgebungsvariablen (die protokolliert oder exponiert werden können). Ein CSI-Treiber vermeidet es, das Secret überhaupt in etcd zu speichern.
Verschlüsseln und authentifizieren Sie automatisch den gesamten Pod-zu-Pod-Netzwerkverkehr.
Stellen Sie ein Service Mesh wie Istio oder Linkerd bereit. Das Mesh injiziert einen Sidecar-Proxy in jeden Pod, um die mTLS-Verschlüsselung, Authentifizierung und Richtliniendurchsetzung zu handhaben.
Warum: Ein Service Mesh bietet transparente Zero-Trust-Netzwerke, ohne Änderungen am Anwendungscode zu erfordern, und sichert die gesamte interne Dienstkommunikation.
Lieferketten-Sicherheit
Verhindern Sie die Bereitstellung von Container-Images mit bekannten Schwachstellen (CVEs).
Integrieren Sie einen Scanner wie Trivy oder Grype in die CI/CD-Pipeline. Brechen Sie den Build ab, wenn die Schwachstellen einen definierten Schweregrad (z. B. HIGH oder CRITICAL) überschreiten.
Warum: Dieser "Shift-Left"-Ansatz erkennt Schwachstellen frühzeitig, bevor sie in Produktion gehen, und reduziert die Angriffsfläche laufender Anwendungen drastisch.
Stellen Sie sicher, dass nur vertrauenswürdige, unveränderte Container-Images im Cluster bereitgestellt werden.
Signieren Sie Images mit `cosign` während des CI-Build-Prozesses. Verwenden Sie eine Policy-Engine (Kyverno, OPA Gatekeeper) als Admission Controller, um die Signatur vor der Erstellung eines Pods gegen einen öffentlichen Schlüssel zu überprüfen.
Warum: Kryptografische Signierung bietet starke Garantien für die Integrität des Images (es wurde nicht manipuliert) und die Authentizität (es stammt aus einer vertrauenswürdigen Quelle).
Minimieren Sie die Angriffsfläche innerhalb eines Container-Images selbst.
Verwenden Sie minimale Basis-Images (z. B. distroless, Alpine). Verwenden Sie ein mehrstufiges Dockerfile, um Build-Tools zu verwerfen. Legen Sie einen Nicht-Root-Benutzer mit der `USER`-Anweisung fest. Verwenden Sie `.dockerignore`, um sensible Dateien auszuschließen.
Warum: Ein minimales Image enthält weniger Pakete und Tools, bietet weniger potenzielle Schwachstellen und erschwert einem Angreifer das Pivoting, falls der Container kompromittiert wird.
Erzwingen Sie eine Richtlinie, dass alle bereitgestellten Images aus der privaten Registry der Organisation stammen müssen.
Verwenden Sie einen Admission Controller (wie OPA Gatekeeper oder Kyverno), um eine Richtlinie zu erstellen, die das `image`-Feld aller Container-Spezifikationen gegen eine Zulassungsliste von Registry-Hostnamen validiert.
Warum: Dies verhindert, dass Entwickler nicht vertrauenswürdige oder nicht gescannte Images von öffentlichen Repositories wie Docker Hub ziehen, und stellt sicher, dass der gesamte Code interne Sicherheitsprüfungen durchlaufen hat.
Führen Sie ein Inventar aller Softwarekomponenten und Abhängigkeiten innerhalb eines Container-Images.
Integrieren Sie ein Tool wie `Syft` in die CI/CD-Pipeline, um eine Software Bill of Materials (SBOM) in einem Standardformat wie SPDX oder CycloneDX zu generieren.
Warum: Eine SBOM ist unerlässlich für die Sicherheit der Lieferkette, da sie eine schnelle Identifizierung aller betroffenen Assets ermöglicht, wenn eine neue Schwachstelle in einer Abhängigkeit entdeckt wird.
Identifizieren Sie Sicherheitsfehlkonfigurationen in Kubernetes YAML-Manifesten, bevor sie angewendet werden.
Verwenden Sie in der CI-Pipeline ein Tool wie `trivy config` oder `kubesec`, um Kubernetes-Manifestdateien auf riskante Konfigurationen zu scannen, z. B. Ausführung als Root, Zulassen von Privilegieneskalation oder Mounten sensibler Host-Pfade.
Warum: Diese proaktive Prüfung fängt Sicherheitsprobleme in Infrastructure-as-Code ab, bevor sie Schwachstellen im laufenden Cluster erzeugen.
Monitoring, Logging und Laufzeit-Sicherheit
Erkennen und alarmieren Sie bei verdächtigen Aktivitäten in laufenden Containern oder auf Cluster-Knoten.
Stellen Sie Falco als DaemonSet bereit. Falco verwendet eBPF oder ein Kernelmodul, um Systemaufrufe zu überwachen und bei abnormalem Verhalten basierend auf seinem Regelsatz (z. B. Shell im Container, unerwartete Netzwerkverbindungen) zu alarmieren.
Warum: Falco bietet Echtzeit-Transparenz über das Laufzeitverhalten und ermöglicht die Erkennung von Bedrohungen wie Container-Escapes, Kryptomining oder Datenexfiltration, die statische Scans nicht erkennen können.
Eine Standard-Falco-Regel erzeugt zu viele Fehlalarme.
Erstellen Sie eine benutzerdefinierte Falco-Regeldatei, um die Standardregel zu überschreiben. Fügen Sie Ausnahmen zur `condition` der Regel hinzu, um bekanntes gutes Verhalten auszuschließen, wie z. B. bestimmte Prozesse oder Container-Images (z. B. `and not container.image.repository contains "debug"`).
Warum: Das Anpassen von Regeln ist entscheidend für die Operationalisierung der Laufzeit-Sicherheit. Die Reduzierung von Rauschen stellt sicher, dass Sicherheitsteams sich auf umsetzbare, hochprioritäre Alarme konzentrieren können.
Protokollieren Sie ein chronologisches, unveränderliches Protokoll aller Aktionen, die gegen die Kubernetes-API vorgenommen wurden.
Aktivieren Sie das Audit-Logging auf dem `kube-apiserver`, indem Sie die Flags `--audit-policy-file` und `--audit-log-path` bereitstellen. Konfigurieren Sie die Richtlinie, um zu definieren, was und auf welcher Ebene protokolliert wird.
Warum: Audit-Logs sind unerlässlich für Sicherheitsanalysen, Vorfallsuntersuchungen und Compliance. Sie bieten eine definitive Aufzeichnung darüber, wer wann was getan hat.
Auditieren Sie den Zugriff auf sensible Ressourcen wie Secrets, ohne den Inhalt des Secrets selbst zu protokollieren.
Konfigurieren Sie die Audit-Richtlinienregel für Secrets so, dass sie `level: Metadata` verwendet. Dies protokolliert den Benutzer, Zeitstempel, Ressource und Verb, lässt jedoch die Request- und Response-Bodies weg.
Warum: Dies schafft Verantwortlichkeit dafür, wer auf Secrets zugreift, ohne ein neues Sicherheitsrisiko durch das Schreiben sensibler Daten in die Audit-Logs zu schaffen.
Aggregieren Sie Logs von allen Cluster-Komponenten und Anwendungen für eine zentrale Analyse.
Stellen Sie einen Log-Sammel-Agenten (z. B. Fluentd, Vector) als DaemonSet bereit, um Logs von Knoten zu sammeln und an ein zentrales SIEM oder Log-Management-System (z. B. Elasticsearch, Splunk) weiterzuleiten.
Warum: Zentralisiertes Logging ist entscheidend für die Korrelation von Ereignissen im gesamten Cluster während einer Vorfallsuntersuchung und für die Aufbewahrung langfristiger Aufzeichnungen zur Compliance.
Leiten Sie Falco-Sicherheitsalarme an ein externes System zur Benachrichtigung und Reaktion weiter.
Stellen Sie `Falcosidekick` zusammen mit Falco bereit. Konfigurieren Sie es so, dass es Alarme von Falco empfängt und an Ausgaben wie Slack, PagerDuty oder ein SIEM weiterleitet.
Warum: Falcosidekick bietet einen flexiblen und robusten Mechanismus zur Integration der Echtzeit-Alarme von Falco in bestehende Betriebs- und Sicherheits-Workflows.
Erkennen Sie, ob ein laufender Container modifiziert wurde, was auf eine Kompromittierung hindeuten könnte.
Erzwingen Sie unveränderliche Container mit `readOnlyRootFilesystem: true`. Verwenden Sie ein Laufzeit-Sicherheitstool wie Falco, um Dateischreibvorgänge an unerwarteten Speicherorten zu überwachen und darauf hinzuweisen.
Warum: In einem unveränderlichen Modell werden Container zur Laufzeit nie geändert; sie werden ersetzt. Jede Abweichung von diesem Muster ist ein starker Indikator für eine potenzielle Sicherheitsverletzung.