Aus unserer Kubernetes Werkzeugkiste: der Secret Generator
Secret was?
Secrets lassen sich in Kubernetes für alles Mögliche nutzen. In einem Secret kann beispielsweise ein TLS-Zertifikat, Zugangsdaten zu einer Container-Registry oder ganz altmodisch Passwörter abgelegt werden.
Beim Start einer Anwendung auf Kubernetes kann es vorkommen, dass ihr ein Passwort vorgeben müsst, das aber eigentlich nur für die Applikation selbst benötigt wird. Das kann passieren, wenn ein Datenbank-Container mit einem bestimmten Benutzer-Passwort als Kubernetes-Pod gestartet wird und eine Applikation, ebenfalls als Pod gestartet, dieses Passwort benutzen soll. In solchen Fällen ist der eigentliche Inhalt eines Passworts gar nicht so wichtig, solange es beiden Containern bekannt und hinreichend sicher ist – sprich lang genug und aus einer kryptografisch sicheren Zufallsquelle erstellt. Hier kommt der Kubernetes Secret Generator ins Spiel. Dieser kann als zusätzliche Komponente in eurem Kubernetes-Cluster gestartet werden und anschließend automatisch bestimmte Arten von Secrets wie etwa Passwörter oder SSH-Schlüsselpaare erstellen.
Installation
Der von mir empfohlene Weg zur Installation des Secret Generators nutzt das beliebte Deployment-Tool Helm. Hierzu müsst ihr zunächst das Mittwald Helm Repository installieren:
$ helm repo add mittwald https://helm.mittwald.de
$ helm repo update
Im Anschluss könnt ihr den Operator per `helm install` bzw. `helm upgrade --install` installieren:
$ helm upgrade \
--namespace kube-system \
--install \
kubernetes-secret-generator \
mittwald/kubernetes-secret-generator
Dieser Befehl installiert den Secret Generator, der fortan als eigener Pod im `kube-system`-Namespace läuft.
Passwörter generieren
Ist der Operator einmal installiert, reicht es, einem beliebigen Secret eine Annotation namens `secret-generator.v1.mittwald.de/autogenerate` zuzuweisen. Das kann z. B. so aussehen:
apiVersion: v1
kind: Secret
metadata:
name: my-generated-secret
annotations:
secret-generator.v1.mittwald.de/autogenerate: password
data:
username: bWFydGlu
Dieses Secret enthält bereits einen Wert unter dem Key `username` (der Wert `bWFydGlu` ist lediglich ein Base64-codiertes `martin`). Die Annotation weist den Secret-Generator nun an, diesem Secret einen weiteren Key `password` hinzuzufügen, der ein automatisch generiertes Passwort enthalten sollte.
Nach dem Erstellen dieses Secrets sollte ein darauffolgendes `kubectl get secret my-generated-secret -oyaml` folgende Ausgabe (natürlich mit einem individuell und garantiert zufällig generiertem Passwort!) ergeben:
apiVersion: v1
data:
password: TWVwSU83L2huNXBralNTMHFwU3VKSkkwNmN4NmRpNTBBcVpuVDlLOQ==
username: bWFydGlu
kind: Secret
metadata:
annotations:
secret-generator.v1.mittwald.de/autogenerate: password
secret-generator.v1.mittwald.de/autogenerate-generated-at: |-
2020-10-15T21:13:47+02:00
secret-generator.v1.mittwald.de/secure: "yes"
secret-generator.v1.mittwald.de/type: string
name: my-generated-secret
type: Opaque
Generierte Passwörter verwenden
Die vom Secret Generator generierten Passwörter können anschließend wie ganz normale Kubernetes-Secrets genutzt werden. Wenn ihr z. B. einen MySQL-Container starten wollt (mehr dazu in der offiziellen Doku), könnt ihr das oben generierte Passwort mit folgendem Snippet als root-Passwort benutzen. Das Snippet solltet ihr dafür in die `.env`-Liste des Pod-Templates im `Deployment` oder `StatefulSet` einfügen.
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: my-generated-secret
key: password
Passwörter neu generieren
Hin und wieder möchte ihr womöglich auch mal ein Passwort rotieren – sei es, weil es jemand zu Gesicht bekommen hat, der es nicht hätte sehen sollen, oder als reine Vorsichtsmaßnahme. Auch das unterstützt der Secret Generator: Hierzu müsst ihr in einem beliebigen Secret-Objekt lediglich die Annotation `secret-generator.v1.mittwald.de/regenerate` setzen:
$ kubectl annotate secret my-generated-secret \
secret-generator.v1.mittwald.de/regenerate=true
Falls ihr komplett auf Nummer sicher gehen möchtet, lassen sich mit einem ähnlichen Befehl auch alle automatisch generierten Passwörter neu vergeben:
$ kubectl annotate secrets --all secret-generator.v1.mittwald.de/regenerate=true
Zusammenfassung
Der Kubernetes Secret Generator nimmt uns die Arbeit ab, für jede weitere Applikation ein weiteres Passwort vergeben und im Anschluss verwalten zu müssen. Auch aus Security-Sicht macht er uns das Leben einfacher: Unsere Deployment-Pipelines müssen sich überhaupt nicht mehr mit Passwörtern abgeben. Sie sagen einfach: „Liebe App, bitte generiere dir dein Datenbankpasswort doch selbst und behalte es für dich“. Die generierten Passwörter brauchen das Kubernetes-Cluster zu keinem Zeitpunkt zu verlassen. Und per RBAC kann unberechtigten Personen gänzlich der Zugriff auf `Secret`-Objekte entzogen werden.
Feedback
Ihr habt Anregungen, Feedback oder Bug-Reports für den Secret-Generator? Diese nehmen wir gerne als Github-Issue entgegen. Ausnahmen sind hier allerdings Meldungen zu Sicherheitslücken. In diesem Fall beachtet bitte die Security Policy des Projekts und nutzt die dort angegebenen Kontaktmöglichkeiten. :-)