Amazon-EKS-Sicherheit mit RBAC, sicherem IMDS und Audit-Protokollierung stärken
Kamil Potrec
7. Juli 2021
0 Min. LesezeitFehlkonfigurationen in Infrastructure as Code (IaC) können genauso gefährlich sein wie Schwachstellen im Code. Schon kleine Konfigurationsfehler können dazu führen, dass vertrauliche Daten im Internet lesbar sind oder private Endpunkte und Dashboards für anonyme Nutzer zugänglich und als erster Angriffspunkt missbraucht werden. Aktuelle Erkenntnisse aus der Sicherheitsforschung zeigen, dass Malware zunehmend auf die Kubernetes-Plattform abzielt – ein weiterer Beleg dafür, wie wichtig sichere Konfigurationen sind.
In dieser Blogbeitragsreihe sehen wir uns die Standardeinstellungen von Amazon-Elastic-Kubernetes-Service-(EKS)-Deployments an. Anschließend zeigen wir, wie kleine Fehlkonfigurationen oder unerwünschte Nebeneffekte unsere Cluster gefährden und Sicherheitsprobleme in EKS verursachen können.
Was ist Amazon Elastic Kubernetes Service?
Amazon Elastic Kubernetes Service ist ein verwalteter Kubernetes-Service. AWS übernimmt die Verwaltung der Control-Plane-Komponenten des Clusters. Für die Verwaltung der Worker-Knoten und Cluster-Ressourcen ist der Kunde verantwortlich.
Neben den Vorteilen einer hohen Verfügbarkeit und Skalierbarkeit der Control Plane bietet Amazon EKS eine Integration mit Identity and Access Management zur Verwaltung von rollenbasierter Zugriffskontrolle, die Möglichkeit, Kubernetes-Service-Accounts IAM-Rollen zuzuordnen, verwaltete Knotengruppen zur automatischen Skalierung der Worker-Kapazität je nach Bedarf, zentralisierte Protokollierung und mehr. Eine vollständige Liste der Funktionen finden Sie in der offiziellen Amazon-EKS-Dokumentation.
Zu den Nachteilen eines verwalteten Service zählen neben den zusätzlichen Kosten die eingeschränkte granulare Kontrolle über die Control-Plane-Einstellungen sowie die Tatsache, dass die in der Control-Plane-Datenbank gespeicherten Daten in AWS-eigenen Konten liegen müssen.
Schnelles EKS-Deployment
Amazon EKS lässt sich auf verschiedene Arten bereitstellen, zum Beispiel über eine Webkonsole, das dedizierte Amazon-EKS-Befehlszeilentool oder IaC-Tools wie CloudFormation oder Terraform.
Für die Bereitstellung eines Clusters mit Standardwerten verwenden wir Terraform. Die Terraform-Konfigurationsdateien für diese Demo finden Sie in diesem Repository. Wir verwenden Terraform Cloud, um Terraform-Befehle auszuführen und Zustandsänderungen zu speichern.
Der EKS-Cluster muss innerhalb einer VPC ausgeführt werden. Mit Terraform können Sie eine VPC mithilfe dieses Moduls bereitstellen.
In unserer Demo-Umgebung stellen wir drei private und drei öffentliche Subnetze bereit. Private Subnetze verfügen nicht über eine Standardroute zum Internet-Gateway. Ein NAT-Gateway ermöglicht den privaten Subnetzen den Internetzugriff. Hinweis: Für die Demo stellen wir nur ein einzelnes NAT-Gateway bereit. Die Netzwerkarchitektur unserer Demo-Umgebung ist unten auf hoher Ebene dargestellt.

Der EKS-Cluster benötigt die ID einer vorhandenen VPC sowie Subnetz-IDs, über die die Kommunikation mit den Knotenpools und die Bereitstellung von Load-Balancern für Services und Ingress-Controller erfolgt. Als Teil unserer Demo-Umgebung stellen wir eine selbstverwaltete Knotengruppe mit drei Instanzen bereit.
Mit Terraform Cloud können Sie Pläne über die Benutzeroberfläche oder per Remote-Operationen ausführen. Um Aktionen über die Benutzeroberfläche auszulösen, müssen Sie den Code in das Versionskontrollsystem committen. Mit Remote-Operationen erhalten Sie schnell Feedback zum Zustand lokaler Konfigurationsdateien. Im Hintergrund lädt Terraform ein Archiv der lokalen Konfigurationsdateien auf einen Remote-Server hoch, führt den Befehl dort aus und überträgt die Ergebnisse zurück an Ihr Terminal. Um eine von Terraform Cloud verwaltete Zustandsdatei zu verwenden, müssen wir eine backend-Konfiguration mit dem richtigen Workspace und der richtigen Organisation hinzufügen.
Dafür ist außerdem der API-Zugriff auf Terraform Cloud erforderlich. Einzelheiten zur Konfiguration finden Sie in der offiziellen Terraform-Cloud-Dokumentation.
Der erste Plan zeigt, dass unsere Konfigurationsdateien 44 neue Ressourcen erstellen werden.
Nun können wir die Umgebung über die Terraform-Cloud-Benutzeroberfläche bereitstellen. Anschließend sollten sich auf der Übersichtsseite Ausgabedaten zu unserem neuen Cluster abrufen lassen.

Nach der Bereitstellung der Umgebung können wir anhand der offiziellen AWS-Dokumentation auf den Demo-Cluster zugreifen.
Dieser Cluster dient als Grundlage für unsere Bewertung. Beginnen wir mit der ersten Beobachtung: Wie einfach konnten wir eine Verbindung zum Cluster herstellen?
Zugriff auf die Kubernetes-API einschränken
Der EKS-Service ermöglicht den Zugriff auf die Kubernetes-API über Service-Endpunkte. Standardmäßig ist der Endpunkt des Clusters öffentlich zugänglich. Das bedeutet, dass jeder im Internet versuchen kann, darauf zuzugreifen. Die Kubernetes-API akzeptiert standardmäßig anonyme Anfragen. Sowohl ABAC- als auch RBAC-Autorisierer verlangen jedoch eine ausdrückliche Autorisierung für anonyme bzw. nicht authentifizierte Nutzer. In EKS-Clustern ist RBAC standardmäßig aktiviert. Das können wir anhand der API-Server-Flags überprüfen.
Die Protokolle zeigen außerdem, dass EKS eine Webhook-Token-Authentifizierungsmethode implementiert. Das bedeutet, dass Kubernetes-Nutzer das Authentifizierungstoken über die AWS-API abrufen müssen, die vom Kubernetes-API-Endpunkt des Clusters getrennt ist. Amazon EKS hat keinen Einfluss auf die Autorisierungsentscheidungen des Clusters.
Um noch sicherer zu sein, können wir versuchen, ohne authentifizierte Anmeldedaten eine Verbindung zum Cluster herzustellen. Um anonyme Nutzer zu simulieren, müssen wir eine Anfrage ohne Autorisierungsheader an die API senden. kubectl verfügt über eine sehr nützliche Debug-Option, die alle Anfragen als CURL-Befehle ausgibt, die wir wiederverwenden können.
Wenn wir dieselbe Anfrage ohne den korrekten Autorisierungsheader senden, sehen wir, dass sie nicht autorisiert wurde.
Nachdem wir nun überprüft haben, dass der Zugriff auf unsere Ressourcen standardmäßig zumindest teilweise eingeschränkt ist, sollten wir das Prinzip der mehrschichtigen Verteidigung betrachten. Damit ist gemeint, verschiedene Arten von Sicherheitskontrollen zu schichten, um eineneinzelnen Ausfallpunkt in unserem Sicherheitssystem zu vermeiden. In unserem aktuellen Deployment sind RBAC-Berechtigungen die einzige Maßnahme, die verhindert, dass beliebige Personen aus dem Internet auf unseren Cluster zugreifen.
Diese Konfigurationsdatei zeigt, wie sich anonymer Zugriff einrichten ließe:
Nach dem Anwenden dieser Konfiguration sehen wir, dass die anonyme Anfrage erfolgreich ist:
Die Kubernetes-Entwickler haben Sicherheitsmaßnahmen eingeführt, um sicherzustellen, dass diese Art von Konfiguration ausdrücklich vorgenommen wird. Der Nutzer system:anonymous und die Gruppe system:unauthenticated müssen ausdrücklich im Attribut subjects aufgeführt sein. Platzhalter wie * gewähren diesen beiden Subjekten keinen Zugriff. Sie können das testen, indem Sie in unserem Beispiel den name des Subjekts durch das Zeichen * ersetzen.
Öffentlicher Zugriff auf den Kubernetes-API-Server erhöht außerdem die Auswirkungen eines kompromittierten Anmeldedatensatzes. Bei einer öffentlich zugänglichen API können die gestohlenen Anmeldedaten potenziell von überall auf der Welt verwendet werden. Eine weitere wichtige Begründung dafür, den Kreis der Systeme einzuschränken, die Pakete an den API-Server senden können, ist eine entdeckte Zero-Day-Schwachstelle im Autorisierungsablauf. In der Vergangenheit wurden beispielsweise die Schwachstellen CVE-2019-11253 und CVE-2020-8559 gemeldet.
Die Auswirkungen öffentlicher Endpunkte lassen sich reduzieren, indem Sie den Zugriff auf bestimmte IP-Adressen beschränken. In Terraform wird dies umgesetzt, indem Sie dem Modul die Eigenschaft cluster_endpoint_public_access_cidrs hinzufügen.
Die zweite Möglichkeit besteht darin, den öffentlichen Endpunkt vollständig zu deaktivieren und einen privaten VPC-Endpunkt zu aktivieren. Dazu können im Terraform-Modul die Eigenschaften cluster_endpoint_private_access und cluster_endpoint_public_access aktiviert bzw. deaktiviert werden. Dadurch ist sichergestellt, dass nur Nutzer mit Zugriff auf das VPC-Netzwerk auf den Cluster zugreifen können.
Beide Optionen haben jedoch erhebliche Auswirkungen auf die Betriebskosten. Ein fehlender öffentlicher Endpunkt kann bei der Verwendung eines öffentlichen Continuous-Deployment-Systems wie Terraform Cloud problematisch sein. In unserer Demo-Umgebung führte die Deaktivierung des öffentlichen Endpunkts dazu, dass das Deployment mit folgendem Fehler wegen verweigerten Zugriffs fehlschlug.

Dieser Fehler tritt auf, weil das Terraform-Modul intern versucht, die Config-Map aws-auth zu aktualisieren, was nur über die Kubernetes-API möglich ist. Wie Sie sehen, wurde der FQDN des API-Servers in eine private IP-Adresse aufgelöst, die vom Provider nicht erreicht werden kann. Wir können den Fehler beheben, indem wir die Verwaltung der Config-Map über unser Terraform-Modul deaktivieren. Das bedeutet, dass wir die Autorisierungs-Config-Map von diesem Zeitpunkt an mit einer anderen Methode verwalten müssen.
Um den öffentlichen Endpunkt vollständig zu deaktivieren, müssen Sie ein CD-System implementieren, das entweder innerhalb der VPC mit Zugriff auf den privaten Endpunkt ausgeführt wird oder die Verbindung über einen Proxy herstellt. Dieser Beitrag erklärt anschaulich, wie sich das mit AWS CodePipeline umsetzen lässt. Mit diesem Terraform-Modul können Sie Atlantis innerhalb des AWS-Fargate-Service ausführen.
Auch der Zugriff für Entwickler kann komplizierter werden, da Sie einen Bastion- oder VPN-Service einrichten müssen, um den Zugriff auf den privaten Endpunkt zu ermöglichen.
Zugriff auf den Instance-Metadata-Service einschränken
EKS nutzt Instance-Profile, um einem auf einem Knoten ausgeführten Kubelet AWS-Berechtigungen zu gewähren. Das Kubelet kann über den Instance-Metadata-Service (IMDS) auf diese Anmeldedaten zugreifen. Der IMDS ist über eine HTTP-Anfrage an eine link-lokale IP-Adresse erreichbar. Standardmäßig ist dieser Metadata-Service für alle Pods auf dem Knoten erreichbar. Das lässt sich testen, indem Sie einen Pod ausführen und ein STS-Token abrufen.
Im obigen Beispiel können wir alle dem Knoten zugewiesenen Berechtigungen nutzen. Dies ist ein eindeutiges Sicherheitsproblem durch eine Ausweitung von Berechtigungen, da Pods standardmäßig keinen AWS-Zugriff benötigen sollten.
Die einzige Möglichkeit, dieses Problem zu entschärfen, besteht darin, den Netzwerkzugriff der Pods auf den IMDS einzuschränken. Der IMDS liegt in zwei Versionen vor. Version 1 verwendet ein Anfrage-Antwort-Verfahren und kann von jedem Prozess abgefragt werden, der Pakete an die link-lokale Adresse senden kann. Version 2 basiert auf Sitzungen und ermöglicht es, eine beliebige Time-to-live-(TTL-)Dauer für Antwortnachrichten festzulegen. Laut der AWS-Dokumentation bleibt IMDSv1 neben IMDSv2 verfügbar.
Um das Ausmaß dieses Problems mit nativer AWS-Konfiguration einzuschränken, müssen wir IMDSv1 vollständig deaktivieren. Dazu setzen Sie das Attribut metadata_http_tokens der Worker-Knoten auf required. Als zweiten Schritt beschränken Sie die TTL der Antwortpakete auf 1 – dies entspricht bereits dem Standardverhalten des Service. Bei einer TTL von 1 kann die Kubernetes-Netzwerkschicht das Paket nicht an den Netzwerk-Namespace des Pods weiterleiten.
Das Terraform-Modul für Amazon EKS verwendet Auto-Scaling-Gruppen und Launch-Vorlagen, um Knoten zu erstellen. Daher müssen die Instanzen aktualisiert werden, wenn Sie die Einstellungen des Metadata-Service ändern.
Die Einschränkung dieser Lösung besteht darin, dass jeder Pod, bei dem das Attribut hostNetworking auf true gesetzt ist, weiterhin auf die Anmeldedaten zugreifen kann.
Mit nativen Kubernetes-Netzwerkrichtlinien lässt sich der Zugriff auf link-lokale IP-Adressen ebenfalls einschränken und damit der Zugriff auf den IMDS verhindern. Die AWS-Calico-Dokumentation enthält Anweisungen zur Installation des Calico-CNI-Plugins. Die folgende Netzwerkrichtlinie sollte den Zugriff auf den IMDS verhindern. Das Calico-Plugin isoliert keine Pods, bei denen hostNetwork auf true gesetzt ist. Daher gilt hier derselbe Nachteil wie bei der nativen Lösung, bei der IMDSv1 deaktiviert und die maximale TTL auf 1 gesetzt wird. Netzwerkrichtlinien erfordern allerdings keinen Austausch der Knoten und lassen sich auf bestimmte Pods anwenden, falls der IMDS innerhalb eines Pods benötigt wird.
Protokollierung aktivieren
Nachdem wir uns nun einige Fehlkonfigurationen angesehen haben, die EKS-Cluster externen und internen Bedrohungen aussetzen können, wollen wir prüfen, ob sich diese Ereignisse auditieren lassen. Kubernetes stellt Audit-Logs bereit, mit denen Administratoren alle Aktionen von Cluster-Nutzern und -Diensten überwachen können. Leider sind diese Logs weder in EKS noch in der Standardkonfiguration des Terraform-Moduls standardmäßig aktiviert. Um sie zu aktivieren, müssen wir das Attribut cluster_enabled_log_types verwenden und die erforderlichen Log-Typen angeben.
In EKS lassen sich mehrere Log-Typen unabhängig voneinander aktivieren. Aus Sicherheitssicht interessieren uns vor allem audit- und authenticator-Logs.
Audit-Logs ermöglichen es uns, Kubernetes-Anfragen zu überwachen und den jeweiligen Entitäten zuzuordnen. Beachten Sie, dass Audit-Logs für jede im Cluster ausgeführte Aktion Ereignisse erzeugen und daher große Datenmengen an das konfigurierte Ziel streamen, standardmäßig an CloudWatch. Wenn wir uns auf audit und authenticator beschränken, bleibt das Datenvolumen geringer.
Zum Beispiel können wir nach Änderungen an der aws-config-Map suchen, um festzustellen, ob jemand sie manipuliert hat. Mit dem folgenden Filter lassen sich alle Patch-Ereignisse zu einem Objekt mit dem Namen aws-auth abrufen.
Audit-Ereignisse enthalten sehr nützliche Informationen, die uns dabei helfen können, herauszufinden, wer die Änderung vorgenommen hat, von wo aus die Verbindung hergestellt wurde und vieles mehr.
Diese Logs können auch sehr hilfreich sein, um Zugriffsversuche nicht autorisierter Nutzer auf Ressourcen zu erkennen. Mit der folgenden Abfrage können Sie nach Anfragen eines anonymen Nutzers suchen:
Authenticator-Logs wiederum können uns dabei helfen, nachzuverfolgen, wer versucht, sich beim Cluster anzumelden, und diese Entitäten Kubernetes-Gruppen und -Nutzern zuzuordnen. Aus dem vorherigen Beispiel wissen wir, dass der Nutzer mit der Schlüssel-ID AROAYREY3WYOBFHU7VIRM die ConfigMap geändert hat. Wir wissen jedoch nicht, zu welcher AWS-Entität diese Schlüssel-ID gehört.
Als Nächstes: Erweiterte Absicherung von Amazon EKS
In diesem Blogbeitrag haben wir einige Sicherheitsprobleme untersucht, die bei der Verwendung von Amazon Elastic Kubernetes Service auftreten können, darunter Authentifizierung und Autorisierung sowie der Zugriff auf den Instance Metadata Service. Außerdem haben wir gesehen, wie sich diese Probleme in Produktionsumgebungen entschärfen lassen. Im nächsten Teil dieser Serie untersuchen wir die Multi-Account-Architektur als wichtigen Schritt zur Isolierung von Amazon-EKS-Clustern, die Bedeutung dedizierter IAM-Rollen beim Erstellen von Amazon-EKS-Clustern und den Schutz von Secrets, die in Amazon-EKS-Control-Planes gespeichert sind. Lesen Sie den nächsten Beitrag oder folgen Sie uns auf Twitter unter @snkysec, um benachrichtigt zu werden, sobald er veröffentlicht wird.
Mit dem Scanning von Snyk Infrastructure as Code (Snyk IaC) lassen sich Sicherheitsprobleme bei der Verwendung von Amazon EKS mit Cloud Formation oder Terraform ebenfalls entschärfen: Es erkennt Sicherheitsprobleme in Ihrem Deployment-Code, bevor dieser die Produktionsumgebung erreicht. Melden Sie sich kostenlos an und starten Sie mit dem Scanning!
Sichern Sie Ihre Infrastruktur an der Quelle
Snyk automatisiert die IaC-Sicherheit und Compliance in Workflows und erkennt abweichende sowie fehlende Ressourcen.
