Blog

Verwaltet eure Secrets mit HashiCorp Vault

JUN 13, 2017

HashiCorp Vault in der Produktion betreiben

Henrik Hoegh

Henrik is a DevOps Consultant based in Aarhus. He specializes in Docker, Kubernetes and everything Atlassian. Away from the office Henrik designs loudspeakers and takes a keen interest in quantum physics and astrophotography.

Sicherheit ist wichtiger denn je. Der Schutz eurer Secrets sollte oberste Priorität haben. Dieser Blog zeigt euch, wie ihr in einer Produktionsumgebung startet.

In einer Software-Delivery-Pipeline kommen mehrere Umgebungen und damit viele verschiedene Arten von Secrets zum Einsatz. Wir erstellen unsere Pipelines als Code, können unsere Secrets aber natürlich nicht in der Versionsverwaltung speichern. Bei Praqma stellte uns ein Kunde die Frage, wie sich Zugangsdaten für einen Container-Cluster absichern lassen, der für Builds und Tests genutzt wird.

Hier kommt HashiCorp Vault ins Spiel: ein verschlüsselter Key Store mit Mechanismen zur Steuerung des Zugriffs auf die gespeicherten Werte. Diese Werte können Passwörter, Zertifikate, URLs oder andere sensible Daten sein. Vault unterstützt verschiedene Backends zur Authentifizierung von Benutzern, etwa GitHub, AWS, LDAP und Radius.

Vault lässt sich im sogenannten Dev-Modus sehr einfach ausprobieren. Etwas anspruchsvoller wird es, wenn ihr es in einer Produktionsumgebung einsetzen möchtet. Wir zeigen euch, wie ihr Vault im Produktionsmodus einrichtet und den Zugriff auf die Inhalte steuert.

Los geht’s

Bei Praqma lieben wir Container – daher wäre es nur seltsam, Vault nicht in einem Container auszuführen. Unser Setup basiert auf dem offiziellen Docker-Image für Vault von HashiCorp und einer kostenlosen Web-UI namens djenriquez/vault-ui. Beide findet ihr im Docker Hub.

Ein einfaches Dockerfile für Vault könnte so aussehen:

FROM vault:0.7.0 MAINTAINER Praqma

Und für die UI:

FROM djenriquez/vault-ui:2.1.0 MAINTAINER Praqma

Legt diese in separaten Ordnern namens vault und vault-ui ab. Danach können wir sie erstellen und in den Docker Hub pushen:

docker build -t praqma/vault:0.7.0 vault/. docker build -t praqma/vault-ui:2.0.2 vault-ui/. docker push praqma/vault:0.7.0 docker push praqma/vault-ui:2.0.2

Danach haben wir zwei Images im Docker Hub, die in unserer Organisation einsatzbereit sind.

Netzwerk und Konfiguration vorbereiten

Die Vault-UI muss sich mit dem Container verbinden, auf dem Vault läuft. Erstellen wir daher ein Netzwerk:

docker network create vault-network

Mit folgendem Befehl könnt ihr prüfen, ob das Netzwerk erstellt wurde:

docker network ls NETWORK ID      NAME             DRIVER    SCOPE 7b332ca38df5    bridge           bridge    local 60f40b5e80f7    vault-network    bridge    local

Als Nächstes erstellen wir eine Konfigurationsdatei. Darin müssen wir einen Speicherort für das Backend festlegen – in diesem Fall eine Datei –, den Adressbereich, auf dem Vault lauschen soll, sowie ob TLS deaktiviert werden soll.

Erstellt eine Datei namens vault.conf mit folgendem Inhalt:

backend "file" {   path = "/vault/file/vaultsecrets" } listener "tcp" {    address = "0.0.0.0:8200"    tls_disable = 1  }

Wir speichern die Datei unter /vault/file im Container, da dies eines der Volumes ist, die vom Basis-Container-Image definiert werden. So können wir es bei Bedarf auf dem Host einbinden.

Wir weisen Vault an, auf allen Netzwerkschnittstellen an Port 8200 zu lauschen und TLS zu deaktivieren, da wir keine Zertifikate haben. Wenn ihr Zertifikate habt, fügt im Listener-Abschnitt zwei Zeilen wie diese hinzu:

tls_cert_file = "/root/server.crt" tls_key_file = "/root/server.key"

Denkt daran, eure Zertifikate an den angegebenen Speicherort in den Container zu kopieren.

Vault-Container starten

Jetzt können wir unseren Vault-Container starten:

docker run -d    --hostname vault    --network vault-network    --privileged    --name vault    --cap-add=IPC_LOCK    -v vault.conf:/vault/config/vault.conf    -v /opt/persistant_storage/vault/:/vault/file/ \  praqma/vault:0.7.0 server -config /vault/config/vault.conf

Vault sollte nun laufen. Das könnt ihr mit folgendem Befehl bestätigen:

docker logs vault

Ihr solltet eine Ausgabe wie diese erhalten:

==> Vault server configuration:                       Cgo: disabled                Listener 1: tcp (addr: "0.0.0.0:8200", cluster address: "0.0.0.0:8201", tls: "disabled")                 Log Level: info                     Mlock: supported: true, enabled: true                  Storage: file                   Version: Vault v0.7.0               Version Sha:614deacfca3f3b7162bbf30a36d6fc7362cd47f0 ==> Vault server started! Log data will stream in below:

Hurra, Vault läuft. Initialisieren wir es jetzt, damit wir es verwenden können.

Initialisierung

lock

Startet eine Terminal-Sitzung im Vault-Container:

docker exec -it vault /bin/sh

Setzt eine Umgebungsvariable, um dem Vault-Client mitzuteilen, wohin er sich verbinden soll, und initialisiert anschließend Vault:

export VAULT_ADDR=http://127.0.0.1:8200 vault init

Dadurch erhaltet ihr fünf Schlüssel und ein Root-Token. Beim Start ist Vault versiegelt, sodass kein Zugriff auf Daten möglich ist. Die generierten Schlüssel werden zum Entsiegeln von Vault verwendet. Dafür benötigt ihr mindestens drei Schlüssel.

Unseal Key 1: z+LgaNbDbejE+hxqq9Q87vjBBfQH6VII1Ey/vmiH+Q4B Unseal Key 2: Zmy5jsn/+LQCMKzaM97imgLOQ2XIBHrmms6Oyxdz5eoC Unseal Key 3: xFEtXOUM6w4JMG+4tf4VaXu/bjoMbQx68/YKzMxO5G4D Unseal Key 4: MKsgyCt935cPcKzvNRPE+0MKOveD0GYvCh7ktsTJvp0E Unseal Key 5: kpa0GgeOzC0EcG+NszMzCDp7F6hHuRCzYyZgsR/0vxkFInitial Root Token: 9cfb29e7-0fde-cc24-df72-76ee59f5c712 Vault initialized with 5 keys and a key threshold of 3. Please securely distribute the above keys. When the Vault is re-sealed, restarted, or stopped, you must provide at least 3 of these keys to unseal it again. Vault does not store the master key. Without at least 3 keys, your Vault will remain permanently sealed.

Ihr entsiegelt Vault mit drei der Schlüssel wie folgt:

/ # vault unseal z+LgaNbDbejE+hxqq9Q87vjBBfQH6VII1Ey/vmiH+Q4BSealed: true Key Shares: 5 Key Threshold: 3 Unseal Progress: 1 Unseal Nonce: 88d38704-415f-b945-e00e-747a51aa8f14 / # vault unseal Zmy5jsn/+LQCMKzaM97imgLOQ2XIBHrmms6Oyxdz5eoCSealed: true Key Shares: 5 Key Threshold: 3 Unseal Progress: 2 Unseal Nonce: 88d38704-415f-b945-e00e-747a51aa8f14 / # vault unseal xFEtXOUM6w4JMG+4tf4VaXu/bjoMbQx68/YKzMxO5G4D Sealed: false Key Shares: 5 Key Threshold: 3 Unseal Progress: 0 Unseal Nonce:

Nachdem Vault entsiegelt ist, können wir uns mit dem Root-Token authentifizieren:

/ # vault auth 9cfb29e7-0fde-cc24-df72-76ee59f5c712 Successfully authenticated! You are now logged in. token: 9cfb29e7-0fde-cc24-df72-76ee59f5c712 token_duration: 0 token_policies: [root]

Und wir sind angemeldet.

Wir müssen eine Richtlinie erstellen, die unser Team verwenden kann. Sie gibt ihm die Berechtigungen, die es zum Abrufen von Daten aus Vault benötigt.

Erstellt im Container eine Richtliniendatei im HCL-Format von HashiCorp:

vi /vault/praqma-policy.hcl

Mit folgendem Inhalt:

path "*"{     capabilities = [ "create", "read", "update", "list" ] }

Damit erhalten Nutzer Zugriff auf alles, was mit diesen Vorgängen zusammenhängt, jedoch beispielsweise nicht auf das Löschen von Secrets. Dies dient Demonstrationszwecken und sollte an eure Sicherheitsstandards angepasst werden.

Erstellt anschließend die Richtlinie:

/ # vault policy-write praqma /vault/praqma-policy.hcl Policy 'praqma' written.

Jetzt aktivieren wir ein GitHub-Backend, damit sich unsere Mitarbeiter mit ihrem GitHub-Konto in der Vault-UI anmelden können.

/ # vault auth-enable github Successfully enabled 'github' at 'github'!

Legt die Organisation fest, deren Mitglied ein GitHub-Nutzer sein muss:

/ # vault write auth/github/config organization=Praqma Success! Data written to: auth/github/config
/ # vault write auth/github/map/teams/default value=praqma Success! Data written to: auth/github/map/teams/default

In diesem Beispiel verwenden wir das Team default. Ihr könnt mehrere Teams mit unterschiedlichen Richtlinien haben, etwa ops und dev, um Berechtigungen detaillierter zu steuern.

Startet den Vault-UI-Container

Vault UI

Verlasst den Vault-Container, damit wir den UI-Container starten können.

Wir müssen zwei Umgebungsvariablen festlegen: VAULT_URL_DEFAULT verweist auf den Vault-Server und VAULT_AUTH_DEFAULT legt die Standardauthentifizierungsmethode fest, in diesem Fall GitHub:

docker run -d \  -p 8000:8000 \  --network vault-network \  --hostname vault-ui \  -e VAULT_URL_DEFAULT="http://vault:8200" \  -e VAULT_AUTH_DEFAULT="GITHUB" \  --name vault-ui \  praqma/vault-ui:2.0.2

Mit docker ps sollten zwei laufende Container angezeigt werden: vault und vault-ui:

CONTAINER ID        IMAGE             COMMAND                  CREATED STATUS              PORTS         NAMES 5941ad1aaeb8   praqma/vault-ui:2.0.2  "/entrypoint.sh np..."  5 seconds ago Up 4 seconds  0.0.0.0:8000->8000/tcp  vault-ui d0d126ac150e   praqma/vault:0.7.0   "docker-entrypoint..."   19 minutes ago    Up 19 minutes   8200/tcp vault

Vault lauscht auf Port 8200 und Vault-UI auf Port 8000. Ruft http://localhost:8000 auf. Dort sollte der Anmeldebildschirm von Vault-UI angezeigt werden.

Geht nun zu github.com, klickt unter eurem Profilbild auf „Settings“ und anschließend im linken Menü auf „Personal access tokens“. Klickt auf „Generate new token“, gebt dem Token einen Namen und wählt die Berechtigungen aus, die ihr diesem Token geben möchtet. Ihr benötigt mindestens Leseberechtigungen.

Gebt das Token in Vault-UI ein, um euch anzumelden. Anschließend solltet ihr die Benutzeroberfläche sehen.

Klickt im linken Menü auf „secret“ und dann auf „new secret“. Gebt dem Secret einen Namen und einen Secret-Wert, indem ihr auf das Quadrat neben „(empty object)“ klickt, und klickt anschließend auf „Save“. Der neue Eintrag sollte nun erscheinen. Klickt testweise auf das Papierkorb-Symbol rechts. Es wird die Meldung „Error, Access denied“ angezeigt, wie in unserer zuvor erstellten Richtlinie definiert.

Zusammenfassung

Wir haben die ersten Schritte mit Vault über den Dev-Modus hinaus gemacht. Wir haben gesehen, wie der Vault-Server und eine Benutzeroberfläche für den Überblick ausgeführt und konfiguriert werden.

  • Cloud
  • Sicherheit

Subscribe to our newsletter