Sichere Verwaltung von Kubernetes Secrets mit Sealed Secrets

Hallo zusammen! In unseren bisherigen Beiträgen haben wir gesehen, wie wir unseren Heim-Kubernetes-Cluster mit Hilfe von FluxCD und GitOps automatisieren können. Heute möchte ich euch zeigen, wie wir mit Sealed Secrets unsere Secrets sicher im Git Repository verwalten können. Zeitgleich sind die Daten sicher abgelegt.

Was sind Sealed Secrets?

Sealed Secrets ist ein Tool, entwickelt von Bitnami, das es uns ermöglicht, Kubernetes Secrets sicher zu verschlüsseln, bevor wir sie in unser Git-Repository hochladen. Im Gegensatz zu normalen Secrets, die im Klartext vorliegen und daher ein Sicherheitsrisiko darstellen können, werden Sealed Secrets verschlüsselt und können nur vom Sealed Secrets Controller in deinem Cluster entschlüsselt werden.

Warum Sealed Secrets?

Die Verwaltung von Secrets in einem öffentlichen oder privaten Git Repository stellt ein großes Sicherheitsrisiko dar, wenn diese im Klartext gespeichert sind. Sealed Secrets lösen dieses Problem, indem sie eine zusätzliche Sicherheitsschicht hinzufügen:

  • Verschlüsselung vor Ort: Secrets werden auf deinem eigenen Gerät verschlüsselt, bevor sie gepusht werden.
  • Cluster-spezifische Schlüssel: Jeder Kubernetes-Cluster hat seinen eigenen, einzigartigen Verschlüsselungsschlüssel für Sealed Secrets, was die Sicherheit weiter erhöht.

Installation des Sealed Secrets Controllers über GitOps

Um den Sealed Secrets Controller mit GitOps zu installieren, nutzen wir FluxCD, um die Kubernetes Manifeste aus unserem Git-Repository automatisch anzuwenden. Hier sind die Schritte:

  1. Erstelle eine neuen Namespace unter clustername/bootstrap/namespace
apiVersion: v1
kind: Namespace
metadata:
  name: sealed-secretsCode-Sprache: PHP (php)
  1. Füge das Sealed Secrets Helmrepository in clustername/bootstrap/helmrepository zu deinem Git-Repository hinzu:
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
  name: sealed-secrets
  namespace: default 
spec:
  interval: 15m
  url: https://bitnami-labs.github.io/sealed-secretsCode-Sprache: JavaScript (javascript)
  1. Erstelle eine Kustomization, die auf ein HelmRelease verweist
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: sealed-secrets
  namespace: default 
spec:
  interval: 15m
  path: clustername/apps/sealed-secrets
  prune: true # remove any elements later removed from the above path
  timeout: 2m # if not set, this defaults to interval duration, which is 1h
  sourceRef:
    kind: GitRepository
    name: flux-system
    namespace: flux-system 
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: sealed-secrets
      namespace: sealed-secrets
Code-Sprache: PHP (php)
  1. Konfiguriere das HelmRelease in clustername/apps/sealed-secrets. Ich kopiere gewöhnlich die gesamte mitgelieferte values.yaml eines Helmcharts. Dabei kommentiere ich aber z.B. Tags für Images aus. Diese sollten vom Helmchart kontrolliert werden.
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: sealed-secrets
  namespace: sealed-secrets
spec:
  chart:
    spec:
      chart: sealed-secrets
      version: 2.x
      sourceRef:
        kind: HelmRepository
        name: sealed-secrets
        namespace: default 
  interval: 15m
  timeout: 5m
  releaseName: sealed-secrets
  values:
    global:
      imageRegistry: ""
      imagePullSecrets: []
      storageClass: ""
    kubeVersion: ""
    nameOverride: ""
    fullnameOverride: ""
    namespaceOverride: ""
    commonLabels: {}
    commonAnnotations: {}
    clusterDomain: cluster.local
    extraDeploy: []
    image:
      registry: docker.io
      repository: bitnami/sealed-secrets-controller
      # tag: 0.26.0-debian-12-r2
      digest: ""
    # falls das Keypair in einem eigenen Secret abgelegt
    # wird gibt man hier den Namen an
    secretName: "name-of-the-secret-containing-your-keys"

.........
  1. Committe die Änderungen in dein Git-Repository und pushe sie: Flux wird automatisch die Änderungen erkennen und den Sealed Secrets Controller im Cluster installieren.

Erstellen und Verwalten von Sealed Secrets

Um ein Sealed Secret zu erstellen, verwenden wir das Tool kubeseal. Hier ist ein Beispiel, wie man ein Secret erstellt und es sicher versiegelt:

  1. Erstellen eines normalen Kubernetes Secret: kubectl create secret generic mysecret --namespace=namespace --from-literal=password='geheim' --dry-run=client -o yaml > mysecret.yaml
  2. Versiegeln des Secrets: kubeseal --cert path/to/your/cert < mysecret.yaml > mysealedsecret.yaml
  3. Füge das versiegelte Secret zu deinem Git-Repository hinzu und pushe die Änderungen: Flux wird das versiegelte Secret automatisch im Cluster anwenden.

Best Practices für Sealed Secrets

  • Regelmäßiges Rotieren der Schlüssel: Um die Sicherheit zu erhöhen, wird der Verschlüsselungsschlüssel des Sealed Secrets Controllers regelmäßig erneuert. Die alten Schlüssel behalten ihre Gültigkeit. In der Dokumentation wird das Konzept genau beschrieben.
  • Backup der Schlüssel: Stell sicher, dass du Backups der privaten Schlüssel hast, um im Notfall Sealed Secrets entschlüsseln zu können.

Sicherung und Wiederherstellung der Schlüssel bei Sealed Secrets

Eine der Herausforderungen bei der Verwendung von Sealed Secrets ist die Handhabung der Schlüsselpaare, insbesondere in Szenarien wie Cluster-Neuinstallationen oder Disaster Recovery. Hier sind die Schritte, wie du die Schlüssel sicherst und bei Bedarf wiederherstellst:

Sicherung des privaten und öffentlichen Schlüssels

  1. Sichern des privaten Schlüssels: Der private Schlüssel, der zum Entschlüsseln der Sealed Secrets verwendet wird, ist besonders schützenswert. Er wird im Kubernetes-Cluster als Secret gespeichert und sollte regelmäßig gesichert werden: kubectl get secret -n kube-system sealed-secrets-key -o yaml > sealed-secrets-key.yaml Diese Datei sollte sicher aufbewahrt werden, idealerweise an einem Ort, der sowohl sicher als auch zugänglich ist, um im Notfall eine schnelle Wiederherstellung zu ermöglichen.
  2. Speichern des öffentlichen Schlüssels im Git-Repository: Der öffentliche Schlüssel, der zum Versiegeln neuer Secrets verwendet wird, kann und sollte im Git-Repository gespeichert werden, damit Entwickler und CI/CD-Systeme darauf zugreifen und neue Sealed Secrets erstellen können: kubeseal --fetch-cert > my-cluster-sealed-secrets-cert.pem Dieser Schritt ermöglicht es, den öffentlichen Schlüssel zu teilen, ohne die Sicherheit zu gefährden. Speichere die .pem Datei in deinem Git-Repository unter einem Pfad wie ./clusters/my-cluster/certs/.

Wiederherstellung der Schlüssel

Bei einer Neuinstallation des Clusters oder nach einem Datenverlust muss das Schlüsselpaar wieder im System bekannt gemacht werden, bevor irgendwelche Sealed Secrets verwendet werden können. Dies geschieht durch das Wiederherstellen des privaten Schlüssels aus deiner Sicherung:

kubectl apply -f sealed-secrets-key.yaml

Nachdem der private Schlüssel wiederhergestellt wurde, kann der Sealed Secrets Controller weiterhin alle bestehenden Sealed Secrets entschlüsseln, ohne dass diese neu erstellt werden müssen.

Hinweis zur Cluster-Neuinstallation

Es ist wichtig zu beachten, dass bei einer kompletten Neuinstallation des Clusters ein manueller Eingriff erforderlich ist, um das Schlüsselpaar wiederherzustellen. Ohne den ursprünglichen privaten Schlüssel sind alle vorhandenen Sealed Secrets wertlos und können nicht mehr entschlüsselt werden. Daher ist die regelmäßige Sicherung und sorgfältige Handhabung dieser Schlüssel von entscheidender Bedeutung für die Sicherheit und Funktionalität des Clusters.

Fazit

Mit Sealed Secrets bieten wir eine sichere Methode, um Kubernetes Secrets in einer GitOps-Umgebung zu verwalten. Durch das korrekte Sichern und Wiederherstellen der Schlüssel können wir die Integrität und Verfügbarkeit unserer geheimen Daten auch bei Neuinstallationen oder Datenverlusten gewährleisten. Dies gewährleistet, dass unser Cluster sicher und effizient weiterlaufen kann, ohne dass eine Neuerstellung aller Secrets erforderlich ist.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert