Installation von HashiCorp Vault auf CODE-DE FRA1-1 Magnum

In Kubernetes ist ein Secret ein Objekt, das Passwörter, Token, Schlüssel oder andere kleine Datenstücke enthält. Die Verwendung von Secrets sorgt dafür, dass die Wahrscheinlichkeit, vertrauliche Daten beim Erstellen, Ausführen und Bearbeiten von Pods preiszugeben, viel geringer ist. Das Hauptproblem besteht darin, dass Secrets unverschlüsselt in etcd gespeichert werden, so dass jeder mit

  • API-Zugang, sowie jeder, der

  • einen Pod oder eine Anwendung in einem Namespace erstellen kann

kann auch ein Secret abrufen oder ändern.

Sie können eine Reihe von Strategien anwenden, um die Sicherheit des Clusters zu verbessern, oder Sie können eine spezielle Lösung installieren, z. B. HashiCorp Vault. Es bietet

  • sichere Speicherung aller Arten von Secrets - Passwörter, TLS-Zertifikate, Datenbank-Anmeldeinformationen, API-Schlüssel und andere,

  • Verschlüsselung aller Daten,

  • dynamische Bereitstellung der Zugangsdaten,

  • granulare Zugriffsrichtlinien für Benutzer, Anwendungen und Dienste,

  • Protokollierung und Prüfung der Datennutzung,

  • Entzug oder Löschung von Schlüsseln oder Secrets,

  • Einstellung eines automatischen Wechsels der Secrets - für Administratoren und Nutzer gleichermaßen.

In diesem Artikel werden wir HashiCorp Vault in einem Magnum Kubernetes-Cluster installieren, auf der CODE-DE FRA1-1 Cloud.

Was wir behandeln werden

  • Installation von selbstsignierten TLS-Zertifikaten mit CFSSL

  • Erzeugen von Zertifikaten für die Verschlüsselung des Datenverkehrs mit Vault

  • Installation des Consul Speicher-Backends für Hochverfügbarkeit

  • Vault installieren

  • Versiegeln und Entsiegeln des Tresors (Vault)

  • Entsiegeln des Vault

  • Vault UI ausführen

  • livenessProbe auf Produktionswert zurücksetzen

  • Fehlersuche

Prerequisites

Nr. 1 Konto

Sie benötigen ein Hosting-Konto mit Zugriff auf die Horizon-Schnittstelle: https://cloud.fra1-1.cloudferro.com/auth/login/?next=/.

Nr. 2 Kenntnisse über kubectl

Sie sollten einen entsprechenden Kubernetes-Cluster eingerichtet haben, auf den kubectl verweist Zugriff auf Kubernetes-Cluster nach der Bereitstellung mit Kubectl auf CODE-DE OpenStack Magnum

Nr. 3 Kenntnisse über den Einsatz von Helm-Diagrammen

Dieser Artikel führt Sie in die Helm-Diagramme auf Kubernetes ein:

Einsatz von Helm Charts auf Magnum Kubernetes-Clustern auf der CODE-DE FRA1-1 Cloud

Schritt 1 CFSSL installieren

Um sicherzustellen, dass die Vault-Kommunikation mit dem Cluster verschlüsselt ist, müssen wir TLS-Zertifikate bereitstellen.

Wir werden selbstsignierte TLS-Zertifikate verwenden, die von einer privaten Zertifizierungsstelle ausgestellt wurden. Um sie zu generieren, werden wir die CFSSL-Dienstprogramme verwenden: cfssl und cfssljson.

cfssl ist ein CLI-Dienstprogramm. cfssljson nimmt die JSON-Ausgabe von cfssl und schreibt Zertifikate, Schlüssel und CSR (Certificate Signing Requests).

Wir müssen die Binärdateien der beiden Tools herunterladen: cfssl und cfssljson von https://github.com/cloudflare/cfssl herunter und machen sie ausführbar:

curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssl_1.6.3_linux_amd64 -o cfssl
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64 -o cfssljson
chmod +x cfssl
chmod +x cfssljson

Dann müssen wir sie auch zu unserem Pfad hinzufügen:

sudo mv cfssl cfssljson /usr/local/bin

Schritt 2 Erzeugen von TLS-Zertifikaten

Bevor wir beginnen, erstellen wir einen dedizierten Namespace, in dem alle Vault-bezogenen Kubernetes-Ressourcen liegen werden:

kubectl create namespace vault

Wir müssen zwei Sätze von Zertifikaten ausstellen. Der erste Satz wird ein Stammzertifikat für die Zertifizierungsstelle sein. Der zweite Satz verweist auf das CA-Zertifikat und erstellt das eigentliche Vault-Zertifikat.

Um die Schlüsselanforderung für die Zertifizierungsstelle zu erstellen, stützen wir uns auf eine JSON-Datei ca-csr.json. Erstellen Sie diese Datei in Ihrem bevorzugten Editor, und wenn Sie möchten, können Sie die Zertifikatsdetails für Ihren eigenen Anwendungsfall ersetzen:

ca-csr.json

{
  "hosts": [
    "cluster.local"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
        "C": "Poland",
        "L": "Warsaw",
        "O": "MyOrganization"
    }
  ]
}

Geben Sie dann den Befehl zum Erzeugen eines selbstsignierten Root-CA-Zertifikats ein.

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

Sie sollten eine vergleichbare Ausgabe sehen:

2023/01/02 15:27:36 [INFO] generating a new CA key and certificate from CSR
2023/01/02 15:27:36 [INFO] generate received request
2023/01/02 15:27:36 [INFO] received CSR
2023/01/02 15:27:36 [INFO] generating key: rsa-2048
2023/01/02 15:27:36 [INFO] encoded CSR
2023/01/02 15:27:36 [INFO] signed certificate with serial number 472447709029717049436439292623827313295747809061

Außerdem werden dadurch drei Entitäten erzeugt:

  • the private key,

  • the CSR, and the

  • self-signed certificate (ca.pem, ca.csr, ca-key.pem).

Der nächste Schritt besteht darin, Vault-Zertifikate zu erstellen, die auf die private CA verweisen. Erstellen Sie dazu zunächst eine Konfigurationsdatei ca-config.json, um die Standardkonfiguration außer Kraft zu setzen. Dies ist besonders nützlich, um die Gültigkeit von Zertifikaten zu ändern:

ca-config.json

{
  "signing": {
    "default": {
      "expiry": "17520h"
    },
    "profiles": {
      "default": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "17520h"
      }
    }
  }
}

Erzeugen Sie dann die Vault-Schlüssel unter Bezugnahme auf diese Datei und die CA-Schlüssel:

cfssl gencert \
  -ca ./ca.pem \
  -ca-key ./ca-key.pem \
  -config ca-config.json \
  -profile default \
  -hostname="vault,vault.vault.svc.cluster.local,localhost,127.0.0.1" \
  ca-csr.json | cfssljson -bare vault

Das Ergebnis wird wie folgt aussehen:

2023/01/02 16:19:52 [INFO] generate received request
2023/01/02 16:19:52 [INFO] received CSR
2023/01/02 16:19:52 [INFO] generating key: rsa-2048
2023/01/02 16:19:52 [INFO] encoded CSR
2023/01/02 16:19:52 [INFO] signed certificate with serial number 709743788174272015258726707100830785425213226283

Außerdem werden drei weitere Dateien in Ihrem Arbeitsordner erstellt: vault.pem, vault.csr, vault-key.pem.

Der letzte Schritt besteht darin, die generierten Schlüssel als Kubernetes TLS Secrets in unserem Cluster zu speichern:

kubectl -n vault create secret tls tls-ca --cert ./ca.pem --key ./ca-key.pem -n vault
kubectl -n vault create secret tls tls-server --cert ./vault.pem --key ./vault-key.pem -n vault

Die Benennung dieser Secrets entspricht den Standardnamen der Vault Helm-Karte.

Schritt 3 Installieren Sie das Consul Helm-Diagramm

Das Consul-Backend wird die Hochverfügbarkeit unserer Vault-Installation sicherstellen. Consul wird in einem Namespace leben, den wir bereits erstellt haben, vault.

Hier ist eine Override-Konfigurationsdatei für das Consul Helm-Diagramm: consul-values.yaml.

consul-values.yaml

global:
  datacenter: vault-kubernetes-guide

client:
  enabled: true

server:
  replicas: 1
  bootstrapExpect: 1
  disruptionBudget:
    maxUnavailable: 0

Installieren Sie nun das hashicorp-Repository von Helm-Charts und stellen Sie sicher, dass vault darin enthalten ist:

helm repo add hashicorp https://helm.releases.hashicorp.com
helm search repo hashicorp/vault

Als letzten Schritt installieren Sie Consul chart:

helm install consul hashicorp/consul -f consul-values.yaml -n vault

Dies ist der Bericht über den Erfolg der Installation:

NAME: consul
LAST DEPLOYED: Thu Feb  9 18:52:58 2023
NAMESPACE: vault
STATUS: deployed
REVISION: 1
NOTES:
Thank you for installing HashiCorp Consul!

Ihre Freigabe heißt consul.

In Kürze werden mehrere Consul-Pods im Namespace vault bereitgestellt. Führen Sie den folgenden Befehl aus, um dies zu überprüfen:

kubectl get pods -n vault

Warten Sie, bis alle Pods Laufen und fahren Sie dann mit dem nächsten Schritt fort.

Schritt 4 Installieren Sie das Vault Helm-Diagramm

We are now ready to install Vault.

Zunächst stellen wir die Datei vault-values.yaml bereit, die die Konfigurationsdatei für das Vault Helm-Diagramm überschreibt. Diese Überschreibung sorgt dafür, dass die Verschlüsselung und die Hochverfügbarkeit aktiviert werden, eine längere Zeit für readinessProbe eingestellt wird und die Benutzeroberfläche als LoadBalancer-Service-Typ dargestellt wird:

vault-values.yaml

# Vault Helm Chart Value Overrides
global:
  enabled: true
  tlsDisable: false

injector:
  enabled: true
  image:
    repository: "hashicorp/vault-k8s"
    tag: "0.14.1"

  resources:
  requests:
    memory: 500Mi
    cpu: 500m
  limits:
    memory: 1000Mi
    cpu: 1000m

server:
  # These Resource Limits are in line with node requirements in the
  # Vault Reference Architecture for a Small Cluster

  image:
    repository: "hashicorp/vault"
    tag: "1.9.2"

  # For HA configuration and because we need to manually init the vault,
  # we need to define custom readiness/liveness Probe settings
  readinessProbe:
    enabled: true
    path: "/v1/sys/health?standbyok=true&sealedcode=204&uninitcode=204"
  livenessProbe:
    enabled: true
    path: "/v1/sys/health?standbyok=true"
    initialDelaySeconds: 360

  extraEnvironmentVars:
    VAULT_CACERT: /vault/userconfig/tls-ca/tls.crt

  # extraVolumes is a list of extra volumes to mount. These will be exposed
  # to Vault in the path `/vault/userconfig/<name>/`.
  # These reflect the Kubernetes vault and ca secrets created
  extraVolumes:
    - type: secret
      name: tls-server
    - type: secret
      name: tls-ca

  standalone:
    enabled: false

  # Run Vault in "HA" mode.
  ha:
    enabled: true
    replicas: 3
    config: |
      ui = true

      listener "tcp" {
        tls_disable = 0
        address     = "0.0.0.0:8200"
        tls_cert_file = "/vault/userconfig/tls-server/tls.crt"
        tls_key_file = "/vault/userconfig/tls-server/tls.key"
        tls_min_version = "tls12"
      }
      storage "consul" {
        path = "vault"
        address = "consul-consul-server:8500"
      }


# Vault UI
ui:
  enabled: true
  serviceType: "LoadBalancer"
  serviceNodePort: null
  externalPort: 8200

Anschließend starten Sie die Installation:

helm install vault hashicorp/vault -n vault -f vault-values.yaml

Auf diese Weise werden mehrere Pods erstellt:

kubectl get pods -n vault
NAME                                                  READY   STATUS    RESTARTS   AGE
consul-consul-client-655fq                            1/1     Running   0          104s
consul-consul-client-dkngt                            1/1     Running   0          104s
consul-consul-client-nnbnl                            1/1     Running   0          104s
consul-consul-connect-injector-8447d8d97b-8hkj8       1/1     Running   0          104s
consul-consul-server-0                                1/1     Running   0          104s
consul-consul-webhook-cert-manager-7c4ccbdd4c-d89bw   1/1     Running   0          104s
vault-0                                               1/1     Running   0          23s
vault-1                                               1/1     Running   0          23s
vault-2                                               1/1     Running   0          23s
vault-agent-injector-6c7cfc768-kv968                  1/1     Running   0          23s

Versiegeln und Entsiegeln des Tresors (Vault)

Direkt nach der Installation startet der Vault-Server in einem versiegelten Zustand. Er weiß, wo und wie er auf den physischen Speicher zugreifen kann, aber er verfügt nicht über den Schlüssel, um ihn zu entschlüsseln. Die einzigen Operationen, die Sie durchführen können, wenn Vault versiegelt ist, sind

  • den Tresor entsiegeln und

  • den Status des Siegels zu überprüfen.

Der umgekehrte Prozess, Entsiegelung genannt, besteht in der Erstellung des Klartext-Stammschlüssels, der zum Lesen des Entschlüsselungsschlüssels erforderlich ist.

Im wirklichen Leben gäbe es einen Administrator, der zunächst die so genannten Schlüsselanteile oder Entschlüsselungsschlüssel, d. h. einen Satz von genau fünf Textzeichenfolgen, erzeugen könnte. Dann würde er diese Schlüssel an zwei oder mehr Personen verteilen, so dass die Geheimnisse für einen potenziellen Angreifer schwer zu ermitteln sind. Und um die Entsiegelung durchzuführen, müssten mindestens drei dieser fünf Zeichenfolgen dem Tresorraum vorgelegt werden, in beliebiger Reihenfolge.

In diesem Artikel sind Sie jedoch sowohl der Administrator als auch der Benutzer und können die Dinge auf Ihre Weise einrichten. Zuerst werden Sie

  • die Schlüssel generieren und sie gut sichtbar aufbewahren, und dann

  • geben Sie drei dieser fünf Zeichenfolgen wieder in das System ein.

Sie haben eine begrenzte, aber ausreichende Zeit für die Eingabe der Schlüssel; der Wert livenessProbe in der Datei vault-values.yaml beträgt 360 Sekunden, was Ihnen ausreichend Zeit für die Eingabe der Schlüssel gibt.

Am Ende des Artikels zeigen wir, wie Sie diesen Wert interaktiv auf 60 Sekunden setzen können, damit der Cluster den Zustand der Pods häufiger überprüfen kann.

Schritt 5 Entsiegeln des Tresors (Vault)

Drei Knoten im Kubernetes-Cluster repräsentieren den Vault und heißen vault-0, vault-1, vault-2. Um den Vault funktionsfähig zu machen, müssen Sie alle drei entsiegeln.

Zunächst, öffnen Sie den Container vault-0:

kubectl -n vault exec -it vault-0 -- sh

Holen Sie dann aus dem Inneren des Pods die Schlüssel:

vault operator init

Das Ergebnis ist folgendes: Sie erhalten die 5 Entsiegelungsschlüssel und ein Root-Token. Speichern Sie diese Schlüssel in Notepad, damit Sie später bequem auf sie zugreifen können:

Unseal Key 1: jcJj2ukVBNG5K01PX3UkskPotc+tGAvalG5CqBveS6LN
Unseal Key 2: OBzqfTYL9lmmvuewk85kPxpgc0D/CDVXrY9cdBElA3hJ
Unseal Key 3: M6QysiGixui4SlqB7Jdgv0jaHn8m45V91iabrxRvNo6v
Unseal Key 4: H7T5BHR2isbBSHfu2q4aKG0hvvA13uXlT9799whxmuL+
Unseal Key 5: rtbXv3TqdUeN3luelJa8OOI/CKlILANXxFVkyE/SKv4c

Initial Root Token: s.Pt7xVk5rShSuIJqRPqBFWY5H

Dann entsiegeln Sie die Kapsel vault-0, indem Sie Folgendes eingebeng:

vault operator unseal

Sie werden zur Eingabe des Schlüssels aufgefordert, fügen Sie dann Schlüssel 1 aus Ihrem Notizblock ein. Wiederholen Sie diesen Vorgang dreimal im vault-0-Pod, wobei Sie jedes Mal einen anderen der fünf soeben erzeugten Schlüssel eingeben.

So sieht der gesamte Vorgang aus:

../_images/unsealing_the_pod.png

Im dritten Schritt werden die Werte Initialized auf true und sealed auf false gesetzt:

Key                    Value
---                    -----
Seal Type              shamir
Initialized            true
Sealed                 false
...                    ...

Der Pod ist entsiegelt.

Wiederholen Sie nun den gleichen Vorgang für die *vault-1* **und vault-2 Pods.

Um die Verwendung der Konsole in vault-0 zu beenden, drücken Sie Strg-D auf der Tastatur. Geben Sie dann vault-1 mit dem Befehl

kubectl -n vault exec -it vault-1 -- sh

und entsperren Sie es durch Eingabe von mindestens drei Schlüsseln. Dann das gleiche Verfahren für Vault-2. Erst wenn alle drei Hülsen entsiegelt sind, wird der Tresor aktiv.

Schritt 6 Vault UI ausführen

Mit unserer Konfiguration ist Vault UI auf Port 8200 eines dedizierten LoadBalancers, der erstellt wurde, verfügbar.

Um den LoadBalancer zu überprüfen, führen Sie aus:

kubectl -n vault get svc

Überprüfen Sie die externe IP des LoadBalancers (dies kann einige Minuten dauern, bis die externe IP verfügbar ist):

NAME                             TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)                                                                            AGE
...
vault-ui                         LoadBalancer   10.254.49.9      64.225.129.145   8200:32091/TCP                                                                     143m

Geben Sie die externe IP-Adresse in den Browser ein und geben Sie dabei HTTPS und Port 8200 an. Die Website fragt Sie möglicherweise nach dem Zertifikat und meldet, dass ein Risiko bei der Ausführung besteht. Wenn Sie alle Risiken akzeptieren, sollte die Vault-Benutzeroberfläche verfügbar sein, ähnlich wie in der Abbildung unten. Geben Sie zur Anmeldung das Token an, das Sie zuvor erhalten haben:

../_images/vault_created.png

Sie können den Tresor jetzt benutzen.

../_images/start_using_vault.png

Rückseten der livenessProbe auf den Produktionswert

Die livenessProbe in Kubernetes ist die Zeit, in der das System den Zustand der Knoten überprüft. Normalerweise wäre das für Sie nicht von Belang, aber wenn Sie den Vault nicht innerhalb dieser Zeitspanne entsiegeln, wird die Entsiegelung nicht funktionieren. Unter normalen Umständen würde der Wert 60 Sekunden betragen, so dass das System im Falle einer Störung innerhalb einer Minute statt sechs reagieren würde. Es ist jedoch sehr schwierig, drei Strings innerhalb einer Minute zu kopieren und einzugeben, wie es bei einem Wert 60 in der Datei vault-values.yaml der Fall wäre. Sie würden fast unweigerlich den Kubernetes-Fehler 137 bekommen, was bedeutet, dass Sie die erforderlichen Operationen nicht rechtzeitig durchgeführt haben.

In der Datei vault-values.yaml wird im folgenden Abschnitt 360 Sekunden als Zeit für die Aktivierung der livenessProbe eingestellt:

livenessProbe:
  enabled: true
  path: "/v1/sys/health?standbyok=true"
  initialDelaySeconds: 360

Um den Wert von livenessProbe auf 60 zurückzusetzen, führen Sie den Befehl aus:

kubectl edit statefulset vault -n vault

Sie können nun auf das Äquivalent der Datei vault-values.yaml innerhalb des Kubernetes-Clusters zugreifen. Der Befehl ruft automatisch einen Vim-ähnlichen Editor auf. Drücken Sie also die Taste O auf der Tastatur, um den Wert damit zu ändern:

../_images/vim_editor_change.png

Wenn Sie fertig sind, speichern Sie und verlassen Sie Vim mit der Standard-Syntax :w und :q.

Fehlersuche

Überprüfen Sie die Ereignisse, die Hinweise darauf geben können, was verbessert werden muss:

kubectl get events -n vault

Wenn Fehler auftreten und Sie die Vault-Installation löschen möchten, um den Prozess von Grund auf zu wiederholen, beachten Sie, dass MutatingWebhookConfiguration möglicherweise im Standard-Namensraum verbleibt. Löschen Sie diesen, bevor Sie es erneut versuchen:

kubectl get MutatingWebhookConfiguration

kubectl delete MutatingWebhookConfiguration consul-consul-connect-injector
kubectl delete MutatingWebhookConfiguration vault-agent-injector-cfg

Was als nächstes zu tun ist

Jetzt ist der Vault-Server Teil des Clusters und kann auch von der IP-Adresse aus verwendet werden, unter der er installiert wurde.

Eine weitere Möglichkeit zur Verbesserung der Kubernetes-Sicherheit ist die Sicherung von Anwendungen mit HTTPS über Ingress:

Bereitstellung von HTTPS-Diensten auf Magnum Kubernetes in der CODE-DE FRA1-1 Cloud.