Spricht man über Secrets Management in Kubernetes geht es darum, wie man mit sensiblen Daten (auch genannt „Secrets“), wie z.B. Passwörtern oder private Keys in einer Kubernetes Umgebung umgeht.
In Kubernetes-API gibt es bereits eine Ressource namens „Secret“, die dafür vorgesehen ist, darin sensible Daten ablegen zu können. Die Kubernetes Secrets werden immer Base64 codiert im Cluster abgelegt. Man könnte daher denken, dass sie nicht „sicher“ sein könnten. Base64 kann man ja ganz einfach codieren und encodieren. Wichtig hierbei ist aber, dass hier eine „Codierung“ und nicht eine „Verschlüsselung“ gemeint ist. Der eigentliche Hintergrund Base64 zu verwenden, liegt laut den Kubernetes-Entwicklern somit nicht im Security-Gedanken, sondern darin, dass man so viel einfacher und zuverlässiger unbekannte Zeichen, Zeilenumbrüche oder sogar Binär-Daten verpacken kann.
Die Kubernetes Secrets werden im Etcd Key-Value-Speicher abgelegt.
Der Zugriff ist via Role-Based Access Control (RBAC) abgesichert.
Daher ist es auch in Ordnung bzw. sicher genug einfache Kubernetes Secrets zu verwenden.
Es wird empfohlen die Kubernetes Ressourcen auf deklarative Weise zu erzeugen und zu verwalten. Ein bekannter Ansatz dazu ist das GitOps-Konzept. In dem Fall könnten so auch sensible Daten wie Passwörter in Text- bzw. Yaml-Dateien stehen. Sensible Daten möchte man aber nicht im Klartext lokal oder in einem Git-Repository ablegen. Wie können aber die Secrets trotzdem in Kubernetes erzeugt bzw. verwaltet werden?
Um das Problem zu beheben, gibt es bereits einige Lösungen und Erfahrungen:
https://github.com/getsops/sops
Mit dem Tool „Sops“ kann man die entsprechenden Dateien verschlüsseln, die sensible Daten enthalten um sie dann verschlüsselt z.B. in einem Git-Repository abzulegen. Wenn man nach dem GitOps-Konzept unter anderem mit Hilfe von ArgoCD arbeitet, gibt es dazu ein ArgoCD-Vault-Plugin.
Die komplette Datei wird in einem Helm-Chart values.yaml mit Sops verschlüsselt und in das entsprechende Git-Repository gepushed. ArgoCD kann dann mit Hilfe des Sops-Plugins diese verschlüsselte values.yaml wieder entschlüsseln und somit in Kubernets ausrollen.
Das Arbeiten mit Sops ist sehr unkompliziert. Es eignet sich vor allem für kleine Projekte, da es auch schnell implementiert werden kann.
Allerdings bringt es auch einige Nachteile mit sich. Hier unsere eigenen Erfahrungen mit Sops:
https://github.com/bitnami-labs/sealed-secrets
Sealed Secrets erlaubt es verschlüsselte Secrets in einem Git-Repo abzulegen. Sobald man mittels kubectl ein SealedSecret in einem Kubernetes Cluster anlegt, wird es von einem Sealed Secrets-Controller automatisch entschlüsselt und in ein natives Kubernetes Secret umgewandelt. Das SealedSecret kann nur von dem Controller entschlüsselt werden, der im Zielcluster ausgeführt wird, und niemand sonst (nicht einmal der ursprüngliche Autor) kann das ursprüngliche Secret vom SealedSecret erhalten.
Dinge die uns hier negativ aufgefallen sind:
Für kleinere Projekte und schnelle Erfolge ist Sealed Secrets, ähnlich wie Sops, gut geeignet. Es ist unkompliziert und schnell aufgesetzt.
Im Vergleich zu Sops, schneidet unserer Meinung nach Sealed Secrets etwas besser ab, da es weniger fehleranfällig ist. Des weiteren verschlüsselt man hier nur die reinen Secrets und kann z.B. die anderen Dateien in einem Helm-Chart so belassen wie sie sind.
External Secrets Operator ist ein Kubernetes-Operator, der externe Secret-Management-Systeme wie AWS Secrets Manager, HashiCorp Vault, Google Secrets Manager, Azure Key Vault, IBM Cloud Secrets Manager, CyberArk Conjur und viele mehr integriert. Der Operator liest Informationen von externen APIs und fügt die Werte automatisch in ein Kubernetes-Secret ein.
Diese Lösung setzt also ein vorhandenes Secrets Management voraus und ist daher etwas komplexer. Allerdings ist man durch den Einsatz von External Secrets Operator sehr flexibel, da man nicht auf ein spezielles Secrets-Management-System festgelegt ist. So bietet es sich an, wenn man z.B. sowieso die Cloud Infrastruktur von AWS benutzt, auch deren Secret-Manager zu verwenden. Ebenso könnte man selbst ein eigenes HashiCorp Vault hosten und auch hier den external Secrets Operator anbinden.
Dadurch, dass am Ende echte Kubernetes Native Secrets erzeugt werden, hat man es auch leicht, wenn man z.B. Third-Party Helm-Charts bzw. Tools einsetzt wie z.B. Cert-Manager, Kube-Prometheus-Stack oder Ingress-Nginx und man nur auf diese existierenden Secrets verweisen muss.
Das Tool „Vault“ kommt von der Firma Hashicorp und ist erstmal „nur“ ein Kubernetes unabhängiges System zum Verwalten von Secrets. Daher benötigt man zu Vault selbst noch ein weiteres Tool, um die Secrets auch in Kubernetes zu verteilen:
https://developer.hashicorp.com/vault/docs/platform/k8s/injector Dieser Injector nutzt das Sidecar-Konzept, um Pod-Spezifikationen so zu ändern, dass sie einen Vault Agent-Container enthalten, der Vault-Geheimnisse auf einem gemeinsam genutzten Speichervolume mounted. Er kann zusammen mit dem Vault Helm Chart deployed werden.
Vermutlich ist es einer der sichersten Methoden mit Secrets in Kubernetes umzugehen, da diese nicht einmal als native Kubernetes Secrets erscheinen, sondern direkt in den Pod injected werden. Allerdings muss man für die Benutzung des sidecar agents die Pod-Manifeste verändern. Hier müssen nämlich annotations hinterlegt werden. Wenn man dann noch „Third-Party“-Anwendungen nutzt, welche die Secrets als Environment-Variablen vorliegen haben möchten, geht dies nur über Workarounds, was das ganze sehr verkompliziert.
https://developer.hashicorp.com/vault/docs/platform/k8s/csi Der Vault CSI Provider ist ein „Store Driver“ der auf einer höheren Ebene erlaubt, dass Pods ein CSI Secrets Store Volume mounten und darauf zugreifen können. Das Volume beinhaltet dann die entsprechenden Secrets. Auch hier muss man, ähnlich wie beim sidecar agent injector, für die Benutzung die Pod-Manifeste verändern.
https://developer.hashicorp.com/vault/docs/platform/k8s/vso Der Vault Secrets Operator ist derzeit die jüngste Methode die Vault-Secrets in Kubernetes einzubringen. Er funktioniert ähnlich wie der external secrets operator und wird ebenfalls in Kubernetes deployed. Er kann aus Vault die Secrets auslesen und diese als native Kubernetes Secrets erzeugen und synchronisieren. Er unterstützt die Synchronisierung des gesamten Lebenszyklus des Secret-Managements von einer oder mehreren Vault-Instanzen. Der Operator unterstützt Secret Rotationen für Deployments, ReplicaSets oder StatefulSets. Die Benutzung des Vault Secrets Operator hat den Vorteil, dass man mit Hilfe der echten nativen Kubernetes Secrets sehr flexibel ist. Das erlaubt also auch die einfache Integration in Third-Party Helm-Charts.
https://argocd-vault-plugin.readthedocs.io/ Dieses Plugin wird in dem GitOps Tool ArgoCD installiert. Durch das Plugin ist es möglich, Passwörter in den Manifesten oder Helm-Charts durch Platzhalter zu ersetzen. Der Platzhalter entspricht dann dem Pfad zum Passwort in der Vault-Instanz. Die Verwendung ist daher sehr unkompliziert.
Welche Secret-Management Lösung man einsetzen sollte, hängt immer von eigenen Faktoren ab. Welche public Cloud verwende ich? Welche Datenschutzbestimmungen habe ich? Muss ich auch von extern oder CI/CD-Pipelines an mein Secret-Management heran? Wie groß / komplex ist mein Projekt, lohnt sich der Aufwand einer komplexen Lösung? Wird nach dem GitOps-Konzept gearbeitet?
Für uns hat sich die Kombination aus Hashicorp Vault und dem Vault Secrets Operator durchgesetzt.
Folgende Gründe sprechen dafür:
Vault kann man sowohl in der Hashicorp Cloud Plattform mieten als auch selbst hosten und betreiben. Es gibt für beide Tools bereits fertige Helm-Charts von den Entwicklern selbst. Dadurch, dass man Vault in jeder Cloud aufsetzen kann, ist man nicht abhängig von den jeweiligen Cloud-eigenen Secret-Management-Services. Man kann sich dadurch auf die Secret-Management-Lösung „Vault“ fokussieren und muss sich nicht erst in diverse andere Cloud-Lösungen einarbeiten.
Nicht immer bieten deutsche Public-Clouds fertige Secrets-Management-Services an, was z.B. bei AWS oder Azure der Fall
wäre. Daher müssen wir oft eine eigene Secrets-Management-Software betreiben.
Vault selbst zu hosten ist für uns notwendig, damit wir die gesetzlichen Datenschutzbestimmungen in Deutschland
einhalten können. Wir müssen auch manchmal Secrets von externen Tools oder CI/CD-Pipelines verwalten, daher brauchen wir
ein Secret-Management mit einer API.
Weil „Vault“ als Tool durch die oben genannten Punkte schon festgelegt wurde, stellte sich nur noch die Frage, mit welchem weiteren Tool die Secrets in den Kubernetes-Cluster kommen? Der Sidecar Agent Injector und der Csi-Provider sind für uns nicht in Frage gekommen, da es sehr kompliziert, beziehungsweise unmöglich war, in fertige Third-Party Helm-Charts die jeweiligen Spezifikationen in die Pods einzubauen. Das ArgoCD Vault Plugin wäre für uns zwar passend gewesen, da wir hauptsächlich ArgoCD einsetzen, allerdings wollten wir uns die Möglichkeit offen halten, anstelle von ArgoCD auch andere GitOps-Operators zu verwenden, wie z.B. Flux oder den Gitlab Kubernetes Agent. Somit blieb für uns nur noch der Vault Secrets Operator bzw. auch der „External Secret Operator“. Allerdings kommt der Vault Secrets Operator von Hashicorp selbst. Somit scheint hier die größtmögliche Kompatibilität zu Vault gewährleistet.
In dem nächsten Blogbeitrag aus der DevOps-Kategorie zeigen wir, wie man Vault und den Vault Secrets Operator in einem Kubernetes Cluster selbst deployed und benutzt.
twenty20 GmbH & Co. KG
Hausinger Straße 6
40764 Langenfeld
+49 (0) 2173 167 00 50