Der sichere Umgang mit Zugangsdaten ist kompliziert und mit Aufwand verbunden. Idealerweise verwendet man niemals das gleiche Passwort zweimal, benutzt mehr als die gängigen 8 Zeichen und beschränkt sich nicht nur auf Kleinbuchstaben. Ein gutes Passwort ist lang und unbequem. Post-Its neben dem Monitor sollten damit eigentlich der Vergangenheit angehören. Zum einen passen die Zugangsdaten nicht mehr auf den Notizzettel, zum anderen wird niemand diese mehrere Minuten abtippen wollen, um dann festzustellen die Zahl “1” und den Buchstaben “l” vertauscht zu haben.

Der nächste Schritt ist das regelmässige Ändern aller benutzten Passwörter. Spätestens jetzt wird es Zeit einen Passwort Manager zu nutzen. Der Anwender hat die Wahl aus einem breiten Angebot, egal ob proprietär, OpenSource, Browser Plugin, Cloud Lösung oder integriert im eigenen Betriebssystem - Passwort Manager sind inzwischen halbwegs etabliert und nicht zwangsläufig exotische Werkzeuge von “Computer Profis”.

Anders sieht es leider bei Anwendungen und den dazu gehörigen “technischen Usern” oder “functional accounts” aus. Eine Anwendung oder Service kommt selten ohne Zugangsdaten aus. Datenbanken, andere Services, das firmeninterne LDAP - es gibt eigentlich immer mindestens einen Account der benutzt wird und dessen Passwort entweder in Konfigurationsdateien oder Umgebungsvariablen beim Service hinterlegt ist.

In der Theorie sind diese Daten immer verschlüsselt, werden häufig geändert und es ist nachvollziehbar wer darauf Zugriff hatte. In der Praxis findet man im besten Fall gut gemachte Eigenlösungen, die zwar irgendwie die Zugangsdaten schützen, aber oft nicht komfortabel zu benutzen sind und ein Audit nicht einfach gestalten. Durch die aktuellen Architekturstile hin zu einem verteilten System aus vielen kleinen wiederverwendbaren Services wird dieses Problem natürlich noch verschärft. In Systemlandschaften mit zum Beispiel mehreren Microservices möchte man in der Regel auch deren Zugänge automatisiert verwalten.

Vault bietet eine Art Schlüsselkasten für Zugangsdaten. Diese werden sicher in einem konfigurierbaren Storage-Backend abgelegt. Zugriffe auf diese Daten werden protokolliert. Je nach der Art des Zugangs können ausserdem die Passwörter nach festen Zyklen geändert werden, zum Beispiel jedesmal nachdem eine Session beendet wurde. Ist ein System kompromittiert können gezielt die von der Applikation angeforderten Passwörter getauscht werden.

Schnittstellen und Executable

Die Kommunikation mit Vault findet über eine HTTP-API statt. Im Moment verspricht HashiCorp noch nicht zur aktuellen Schnittstelle rückwärts kompatibel zu bleiben, wird aber ab einer stabilen Version in der Dokumentation darauf hinweisen.

Um die Administration zu vereinfachen bietet Vault auch ein CLI. Intern nutzt der Client allerdings auch die HTTP-Schnittstelle. Ein Nebeneffekt: Bestimmte Sondermethoden die sich nur im CLI-Tool finden wird es dadurch nicht geben.
Zusätzlich maintained HashiCorp noch Libraries für Go und Ruby. Für Java gibt es bisher 2 Implementierungen der Community (“vault-java” und “vault-java-driver”). Beide haben nicht noch zusätzliche Abhängigkeiten, wie zum Beispiel eine HTTP-Library.

Vault selbst besteht lediglich aus einem ~ 32 MB grossen Executable. Wird der Befehl server und eine Konfiguration angegeben, startet ein Vault Server. Ohne den server Befehl dient das Binary als CLI zur API. Mit welchem Server kommuniziert werden soll kann entweder durch zusätzliche Parameter angegeben werden oder einfach in der Umgebungsvariable VAULT_ADDR abgelegt sein.

Storage-Backend

Welches Storage-Backend gewählt werden kann, hängt davon ab, ob Hochverfügbarkeit eine Anforderung ist oder nicht. Hochverfügbarkeit bieten zum Beispiel Consul, etcd, Zookeeper oder DynamoDB. Darüber hinaus sind noch MySQL, PostgreSQL und die Ablage im Dateisystem möglich. Das Speichern der Daten nur im Arbeitsspeicher eignet sich natürlich eher für kleine Tests während der Entwicklung, weniger für den Produktiveinsatz.

Einige der Backends werden von der Community Maintained, offiziell von HashiCorp unterstützt wird natürlich Consul, In-Memory-Storage und die Ablage im Dateisystem.

Initialisierung und erster Start

Nach dem ersten Start muss ein neuer Vault zuerst initialisiert werden. Dabei wird ein interner Key erzeugt mit dem alle Daten im Backend verschlüsselt werden. Dieser Key ist nicht für User oder Administratoren zugänglich. Der interne Vault-Key wird dann nochmals verschlüsselt abgelegt und es werden eine konfigurierbare Anzahl an Master-Keys zur Administration angezeigt.

Um Vault nach dem Serverstart nutzen zu können muss zuerst ein sogenannter “Unsealing”-Prozess gestartet werden. Beim “Unsealing” muss einer oder mehrere der Master-Keys eingegeben werden. Wieviele Keys benötigt werden wird bei der Initialisierung festgelegt.

Hier ein Beispiel bei dem 4 Keys erzeugt werden, wovon 2 zum Unsealing vorhanden sein müssen:

test@fnord:~/vault/data$ vault init --check
Vault is not initialized
test@fnord:~/vault/data$ vault init -key-shares=4 -key-threshold=2
Key 1: b707753c5b9e522830af48fbb93f12b136f0b3f9882bc26a7e0fb976e6cee20001
Key 2: 73a6e28f9919f26240c17315fd087274725544293cdc238dae13ab2061db7acd02
Key 3: c63066172e6492ad9912934fc1ec52374e36e09050787cd017eea5121c21fb7f03
Key 4: e0ffd7f2060ca9f6a01d05d27566b2e5fa04b1924f29fa58152b8f8c74f1514c04
Initial Root Token: 8e8719de-ceaf-52d1-3475-cdebbc7599d1

Vault initialized with 4 keys and a key threshold of 2. Please
securely distribute the above keys. When the Vault is re-sealed,
restarted, or stopped, you must provide at least 2 of these keys
to unseal it again.

Vault does not store the master key. Without at least 2 keys,
your Vault will remain permanently sealed.
test@fnord:~/vault/data$ vault unseal b707753c5b9e522830af48fbb93f12b136f0b3f9882bc26a7e0fb976e6cee20001
Sealed: true
Key Shares: 4
Key Threshold: 2
Unseal Progress: 1

test@fnord:~/vault/data$ vault unseal 73a6e28f9919f26240c17315fd087274725544293cdc238dae13ab2061db7acd02
Sealed: false
Key Shares: 4
Key Threshold: 2
Unseal Progress: 0
Initialisierung und Unsealing

Für weitere Interaktionen wird ein Token zur Authentifizierung benötigt. Mit diesem können dann weitere Tokens erzeugt werden und je nach ACL zum Beispiel der Vault auch wieder geschlossen werden:

test@fnord:~/vault/data$ vault auth
Token (will be hidden):
Successfully authenticated!
token: 8e8719de-ceaf-52d1-3475-cdebbc7599d1
token_duration: 0
token_policies: [root]
test@fnord:~/vault/data$ vault seal
Vault is now sealed.
test@fnord:~/vault/data$ vault status
Sealed: true
Key Shares: 4
Key Threshold: 2
Unseal Progress: 0
Authentifizierung und Sealing

Authentifizierung und ACLs

Vault unterstützt unterschiedliche sogenannte Backends zur Überprüfung von Zugangsdaten. Standardmässig ist das Token Backend unter /auth/token erreichbar. Dort können Tokens erstellt und bevor sie ablaufen auch verlängert werden. Soll ein Token zur Authentifizierung genutzt werden, reicht beim CLI der Aufruf von vault auth <token>. Bei der direkten Nutzung der HTTP-API wird einfach der Header “X-Vault-Token” verwendet. Produktive Installationen sollten natürlich auch deshalb nicht ohne TLS betrieben werden.

Andere Backends unterstützen Anmeldungen auf Basis von Benutzername und Passwort, TLS Client Zertifikaten, bestimmte 2-Faktor-Protokolle oder LDAP und GitHub als Authentifizierungs-Provider.

Technische Accounts können ausserdem über den App-ID Mechanismus abgebildet werden. Hier werden zur Anmeldung am Vault zwei Informationen benötigt: Eine eindeutige App-ID und eine eindeutige User-ID. Die App-ID kann dann zum Beispiel direkt mit der Anwendung provisioniert werden. Die User-ID kann dann beim Start der Anwendung zum Beispiel Maschinen-Abhängig errechnet werden. Denkbar ist ein Hash der MAC-Adresse oder einer anderen physikalischen ID der Hardware mit einem Salt. Damit muss das Configuration-Management zum Beispiel nicht zwangsläufig Zugriff auf die Zugänge erhalten.

Vault legt die gespeicherten Zugangsdaten in einem Baum als Datenstruktur ab. Zu jedem Zweig gibt es dann die üblichen Rechte wie zum Beispiel read, update, create, delete oder list. Zur Vereinfachung gibt es noch Kurzformen, beispielsweise die Kurzform write. Diese umfasst dann die Rechte create, read, update, delete und list.

Das Format für Policies ist JSON oder HashiCorps JSON-kompatible Konfigurationssprache HCL, zum Beispiel:

path "secret/prod/db1" {
	policy = "login"
	capabilities = ["read", "list"]
}
Policy Beispiel HCL

Die Policy kann dann zum Beispiel mit vault policy-write myPolicy file.hal oder cat file.hal | vault policy-write myPolicy - gespeichert werden.

Wird ein User mit einem Passwort oder einem neuen Token angelegt, können dabei die erstellten Policies referenziert werden. Damit sind Rechte an die Art der Authentifizierung gebunden. Möglich werden dadurch Sicherheitskonzepte, welche erweiterte Rechte nur nach einer Authentifizierung mit Benutzername und nicht nur durch ein Token zulassen.

Ablegen und Auslesen von Zugangsdaten

Zugangsdaten werden in unterschiedlichen “Secret Backends” abgelegt. Diese Backends stellen je nach Typ bestimmte Features zur Verfügung.

“Generic” ist das Standard Backend welches immer unter “/secret” zu finden ist. Dort können beliebige Key/Value-Paare gespeichert werden. Dabei ist zu beachten, dass die Keys unverschlüsselt gespeichert sind.
Beim ablegen des Passworts kann ausserdem eine TTL angegeben werden. Diese wird dann beim auslesen in Sekunden als “lease_duration” zurückgegeben. Der Wert ist allerdings rein zur Information an den Client gedacht. Sie gibt den gewünschten Zeitraum an, in dem das Passwort erneut ausgelesen werden sollte. Vault selbst wird nach Ablauf der TTL nicht die Accountdaten entfernen.

Speichern von Testdaten via HTTP und abrufen derselben mit dem CLI:

test@fnord:~$ curl http://localhost:8200/v1/secret/intranet/app1 -d \ '{"username":"myUser", \
"password":"myPass", \
"ttl":"24h"}' \
-H "X-Vault-Token:0846c230-8542-3a1c-1ebc-460ecc28eeab" -v
* Connected to localhost (127.0.0.1) port 8200 (#0)
> POST /v1/secret/intranet/app2 HTTP/1.1
> [..]
> X-Vault-Token:0846c230-8542-3a1c-1ebc-460ecc28eeab
>
* upload completely sent off: 55 out of 55 bytes
< HTTP/1.1 204 No Content
< [..]

test@fnord:~$ vault read secret/intranet/app1
Key               Value
lease_duration    86400
password          myPass
ttl               24h
username          myUser
Beispiel HTTP API und CLI

Weitere Backends und Dynamische Zugänge

Neben dem “Generic”-Backend gibt es noch eine ganze Reihe von weiteren Möglichkeiten Zugänge abzulegen oder “On-the-Fly” zu erzeugen. Ein Beispiel ist hier das SSH Backend:

Auf dem Zielsystem wird als zusätzliches Authentifizierungsmodul (PAM) der Vault-SSH-Helper installiert. Dieser Helper kann dann entweder nur einmal nutzbare Passwörter validieren (OTP) oder ein neues generiertes Schlüsselpaar nutzen. Die Kommunikation mit den Vault-Servern findet verschlüsselt über TLS statt.

Benötigt man nun Zugriff auf eine Maschine im Netz, erhält man über Vault den passenden Zugang. Zugriffe werden auch hier wieder entsprechend protokolliert.
Neben SSH gibt es Momentan noch Backends für AWS, Cassandra und verschiedene SQL Datenbanken.

Der Client erhält beim Anfordern des Zugangs eine Lease-Time und eine Lease-Id. Braucht er den Zugang über die Lease-Time hinaus, kann er mit renew verlängert werden. Bei einem Einbruch im System können Leases dann mit revoke deaktiviert werden. Lease IDs sind hier auch wieder als Pfad aufgebaut, zum Beispiel als “ssh/creds/intranet_backend/12345”. Beim Revoken kann ein Prefix mit angegeben werden. Damit wird es einfach zum Beispiel mit einem Befehl alle Leases der Gruppe intranet_backend zu revoken.

Benutzt man aus irgend einem Grund symmetrische Verschlüsslungsverfahren wie AES gibt es zum Ver- und Entschlüsseln der Daten nur einen einzigen Schlüssel. Möchte man diesen Schlüssel nicht in der Anwendung hinterlegen, kann man das “Transit”-Backend nutzen. Dieses Backend bietet einen API Endpoint, der Daten entgegen nimmt und diese mit dem hinterlegten Key verschlüsselt. Der Key selbst verlässt dabei zu keinem Zeitpunkt den Vault.

Audit Logs

Jeder Request und Response der API kann in einem oder mehreren Audit Backends geloggt werden. Unterstützt wird das Schreiben in eine Datei und/oder Syslog. Sensitive Informationen werden dabei mit HMAC-SHA256 und einem Salt gehasht. Passwörter werden damit nicht direkt geloggt. Ist die Information bekannt, kann sie aber trotzdem über den Hash im Log verfolgt werden.

Logging geschieht immer bevor eine Antwort an die Clients geschickt wird. Blockieren die Logging Backends, erhält der Client keine Antwort. Damit ist sichergestellt, dass wirklich alle Interaktionen protokolliert werden.

Vault Enterprise Features

Natürlich bietet HashiCorp auch entsprechenden “Enterprise-Support” an. Dazu gehört die übliche Hilfe über Telefon/E-Mail. Als zusätzliches Feature enthält man die Möglichkeit Vault mit seinem Hardware Security Modul (HSM) zu integrieren. Davon abgesehen gibt es aber keine weiteren Unterschiede zur Open Source Version.

Fazit

Vault erfüllt die gängigen Anforderungen an den Umgang mit Passwörtern, Tokens, Zertifikaten, Zugriffen usw. Vergleicht man Vault mit gängigen “Priviliged Account”-Management Systemen, bieten diese oft eher stiefmütterlich behandelte zusätzliche Features, wie zum Beispiel das rotieren von Datenbank Passwörtern, den richtigen JDBC-Treiber vorausgesetzt. Der Schwerpunkt liegt dabei eher auf dem Verwalten manuell benutzter Accounts. Wenn es darum geht in Applikationen hinterlegte Zugänge endlich in den Griff zu bekommen ist Vault sicher einen näheren Blick wert. Dabei stellt HashiCorp auf der Projektseite die Usecases vor [1] und bietet neben der üblichen “Getting Started” Dokumentation[2] ein interaktives Tutorial [3] an.

Links & Literatur

  1. Vault Intro https://www.vaultproject.io/intro/  ↩

  2. Vault Installation https://www.vaultproject.io/intro/getting-started/install.html  ↩

  3. Vault Demo https://www.vaultproject.io/#/demo/0  ↩