Das Secret Management System Vault

Vault ermöglicht das verteilte Arbeiten mit Geheimnissen. Diese können über AppRoles und ACLs geschützt werden, was Vault sehr flexibel macht.

Hier zeige ich wie man aus dem internen KV Store in der Version 2 Daten abrufen kann. Der Aufbau ist wie folgt: Es gibt einen Mountpoint administrator in dem ein KV2 Secretstore gemountet ist. In diesem werden Passswörter für Benutzer auf Systemen abgelegt. Damit eine Sortierung einfacher wird, ist eine weitere Ebene im Pfad ORT vorhanden. Der Server heißt server und das Geheimnis password.

Die neuste Version eines Secrets ermitteln

Da der KV2 gegenüber der ersten Version nun über eine Versionierung der Geheimnisse verfügt, muss man nun auch immer die Version abgeben die man abrufen möchte. Dazu kann man aus den Metadaten die neuste Versionsnummer ermitteln.

Allgemeiner Abruf

Die Metadaten sind unterhalb des Mountpoint unter /metadata zu finden. Der Pfad zum Geheimnis muss zusätzlich angehangen werden.

curl -H "X-Vault-Token:s.XXX" -X GET https://vault.XXX.org:443/v1/administrator/metadata/ORT/server/password

Als Ausgabe erhält man ein JSON welches die Metadaten enthält. In versions sind die aktuellen Versionen zu finden. Hier im Beispiel also 1.

{
    "request_id": "680ec30e-3013-6416-8ee8-2937f694b5e2",
    "lease_id": "",
    "renewable": false,
    "lease_duration": 0,
    "data": {
    "cas_required": false,
    "created_time": "2020-03-08T08:51:56.895667901Z",
    "current_version": 1,
    "delete_version_after": "0s",
    "max_versions": 0,
    "oldest_version": 0,
    "updated_time": "2020-03-08T08:51:56.895667901Z",
    "versions": {
        "1": {
        "created_time": "2020-03-08T08:51:56.895667901Z",
        "deletion_time": "",
        "destroyed": false
        }
    }
    },
    "wrap_info": null,
    "warnings": null,
    "auth": null
}

Mit JQ die Version filtern

Mit JQ kann mit die Information recht einfach herausfiltern.

curl -H "X-Vault-Token:s.XXX" -X GET https://vault.XXX.org:443/v1/administrator/metadata/ORT/server/password | jq '.data.versions | keys[0]'

"1"

KV2 Value auslesen

Wenn man die aktuelle Version bestimmt hat, dann kann man die Version eines Geheimisses auslesen. Die Daten befinden sich unterhalb /data.

curl -H "X-Vault-Token:s.XXX" -X GET https://vault.mrpeacock.duckdns.org:443/v1/administrator/data/ORT/server/password?version=1 | jq '.'

Als Antwort erhält man auch hier ein JSON.

{
    "request_id": "4b7613ef-c752-f8b7-dc94-aecd0999d1c0",
    "lease_id": "",
    "renewable": false,
    "lease_duration": 0,
    "data": {
    "data": {
        "password": "admin123"
    },
    "metadata": {
        "created_time": "2020-03-08T08:51:56.895667901Z",
        "deletion_time": "",
        "destroyed": false,
        "version": 1
    }
    },
    "wrap_info": null,
    "warnings": null,
    "auth": null
}

Value mit JQ herausfiltern

Auch hier können wir JQ zur Hilfe nehmen und direkt das Passwort auslesen. Die Informationen stecken, Achtung in data.data. Siehe JSON.

curl -H "X-Vault-Token:s.XXX" -X GET https://vault.XXX.org:443/v1/administrator/data/ORT/server/password?version=1 | jq '.data.data.password'

JQ gibt dann das Passwort aus:

"admin123"

HashiCorp Vault

In diesem Artikel zeige ich wie man HashiCorp Vault hinter einem Reverse Proxy (Nginx) aufsetzt.

Was ist HashiCorp Vault?

Ist eine Secret Management, Encryption as a Service Anwendung von der Amerikanischen Firma HashiCorp.

Installation von Vault mit Docker

Für diesen Artikel setze ich eine funktionieren Docker und NginX Umgebung voraus und gehe nicht weiter auf dessen Konfiguration im Vorfeld ein.

Das Docker-Compose Skript

Ich empfehle die Volumes immer in der nähe des Docker-Compose Skriptes zu halten, so kann alles auf einmal in einem Backup gesichert werden und man hat einen schnelleren überblick was in den Container gemountet wird. Der Container wird Vault auf dem Port 9000 exposen, sodass wir diesen später in der NginX Konfiguration angeben müssen. Der Port kann natürlich beliebig gewählt werden.

version: '2'
services:
  vault:
    image: vault
    container_name: vault
    ports:
      - "9000:9000"
    restart: always
    volumes:
      - ./volumes/logs:/vault/logs
      - ./volumes/file:/vault/file
      - ./volumes/config:/vault/config
    cap_add:
      - IPC_LOCK
    entrypoint: vault server -config=/vault/config/vault.json
    restart: always

Die Konfiguration der Servers erfolgt mit der Datei vault.config in dem ./volumes/config Verzeichnis. Diese verwendet Vault beim starten der Anwendung. Es muss hier der Port angegeben werden unter dem dann die Anwendung erreichbar sein soll. In diesem Beispiel ist es also der Port 9000. Der Schalter proxy_protocol_behaviour ist wichtig, da sonst die Anwendung hinter dem Reverse Proxy nicht zu erreichen ist.

{
  "backend": {
    "file": {
      "path": "/vault/file"
    }
  },
  "listener": {
    "tcp":{
      "address": "0.0.0.0:9000",
      "tls_disable": 1,
      "proxy_protocol_behaviour": "use_always"
    }
  },
  "ui": true
}

Starten sie nun mit docker-compose up den Container, um zu sehen das die Konfigurationsdatei geladen worden ist und prüfen sie ob der Port in dem Listener korrekt gesetzt ist. Prüfen Sie ob nun den Setup Dialog von Vault unter der IP Adresse und Port angezeigt bekommen.

Stoppen sie nun den Container CTRL-C und starten sie ihn neu und verfolgen das Log mit:

docker-compose up -d
docker-compose logs -f

NginX als Reverse Proxy einrichten

Erstellen sie folgende Konfiguration für NginX:

##
#
# Hashicorp Vault
#
##

#
# HTTP -> HTTPS redirect
#
server {
  listen 80;
  server_name vault.XXX.org;

  return 301 https://$server_name$request_uri;
}


server {
  listen 443 ssl http2;
  server_name vault.XXX.org;

  # SSL * cert
  include /etc/nginx/wildcard_ssl.conf;

  location / {
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;

    # Fix the “It appears that your reverse proxy set up is broken" error.
    proxy_pass          http://vault.XXX.org:9000;
    proxy_read_timeout  90;

    proxy_redirect      http://vault.XXX.org:9000 https://vault.XXX.de;
  }
}

Starten sie den Nginx neu, damit die geänderte Konfiguration gelesen werden kann. Vault ist nun fertig installiert und kann konfiguriert werden. Vault sollte nun über HTTPS in der angegebenen FQDN erreichbar sein.

Initialisierung von Vault

Bei dem ersten Start von Vault muss man einen Masterschlüssel erzeugen und diesen in mindestens einen abgeleiteten Schlüssel (derived key). Für Testzwecke reicht es also aus in dem Dialog 1 und 1 einzugeben. Die Anzahl der Schlüssel kann man später per rekeying ändern.

Nun muss das Root-Token und die Schlüssel an einem sicheren Ort gespeichert bzw. an die entsprechenden Personen verteilt werden. Es kann aber auch eine JSON Datei mit allen Schlüssel runter geladen werden.

Unsealing

Wenn Vault gestartet wird, so ist es versiegelt (sealed). Um Vault nutzen zu können (nicht nur UI sondern auch über REST), muss die Versiegelung aufgehoben werden. Dazu müssen die Anzahl der im Threshold vorgegebenen derived Keys nun eigegeben werden, um das Siegel zu entfernen. Dieses ist ein Sicherheitsmerkmal von HashiCorp Vault.