
Secrets nativ in Kubernetes zu verwalten ist nicht sicher: Sie liegen lediglich als Base64-codierter Klartext vor, der in jedem laufenden Pod ausgelesen werden kann.
Disclaimer:
Dieses Tutorial führt Sie Schritt für Schritt durch jede Komponente des Setups. Sie können die Einrichtung selbstverständlich auch mit Terraform erledigen – wer ein derart kritisches Setup jedoch blind aufzieht, läuft in Probleme, die sich ohne fundiertes Verständnis nur schwer lösen lassen.

Natürlich lässt sich ein Secret in Kubernetes verschlüsseln – allerdings nur im Ruhezustand. Sobald es im Pod gemountet ist, liegt es als Datei oder Umgebungsvariable vor und ist innerhalb des Pods problemlos einsehbar. Bei einem Sicherheitsvorfall sind die Daten kompromittiert, sobald jemand Zugriff auf den Pod hat – oder per kubectl auf den Namespace, in dem der Pod läuft.
HashiCorp Vault bietet einen sicheren Weg, Secrets zu verwalten sowie Zugriffe zu auditieren und zu widerrufen. Vault zu installieren und zu betreiben ist eine Sache – die Secrets dann auch in einem Pod nutzbar zu machen eine andere.
Dieser Beitrag zeigt die Installation von Vault auf GKE mit Terraform und Helm. Wie Sie die Secrets anschließend nutzen, lesen Sie in meinem weiteren Blogbeitrag zum transparenten Konsumieren von Secrets aus Vault in einem Pod.
Dieser Ansatz ist deutlich einfacher zu betreiben, wenn Sie nur Vault benötigen und auf erweiterte Consul-Funktionen wie das Consul-Template mit Vault verzichten können.
In diesem Tutorial zeige ich Ihnen, wie Sie ein hochverfügbares Vault mit Google Cloud Storage (GCS) als Backend und durchgängiger TLS-Verschlüsselung aufsetzen.
Hinweis:
Legen Sie das Vault-Setup pro Umgebung separat an, um Upgrades sauber testen zu können und die Umgebungen voneinander zu trennen.
Ich rate davon ab, Vault als Service nach außen freizugeben. Wenn Sie darauf zugreifen müssen, geht das per:
$ kubectl port-forward vault-0 8200:8200Die UI erreichen Sie dann wie weiter unten beschrieben unter https://127.0.0.1:8200.
Müssen VMs auf Vault zugreifen, sollten Sie VPC-Peering einsetzen, da Services und Pods native IPs verwenden – das ist hier aber nicht Thema.
Tutorial:
Überblick:
- TLS-Zertifikate für Vault erstellen
- Einen GCS-Bucket als Vault-Storage-Backend anlegen
- KMS-Keyring und Verschlüsselungsschlüssel für Vault Auto-Unseal anlegen
- Service Accounts für Vault einrichten, damit es auf KMS und das GCS-Storage-Backend zugreifen kann
- Das offizielle HashiCorp-Vault-Helm-Chart per Helm Tillerless installieren
TLS-Zertifikate für Vault erstellen:

Eine der Empfehlungen für Production Hardening lautet, dass die Kommunikation zwischen Vault und seinen Clients sowohl ein- als auch ausgehend per TLS verschlüsselt sein muss.
Wir erstellen ein Zertifikat für:
- die Kubernetes-Vault-Service-Adresse
- 127.0.0.1
Zum Erzeugen der Zertifikate nutzen wir das CloudFlare SSL ToolKit (cfssl und cfssljson).
Die Installation setzt eine funktionierende Go-1.12+-Installation sowie einen korrekt gesetzten GOPATH voraus.
Wichtig: Stellen Sie sicher, dass das GOPATH-bin-Verzeichnis in Ihrem PATH liegt:
export PATH=$GOPATH/bin:$PATHCloudFlare SSL ToolKit installieren:
go get -u github.com/cloudflare/cfssl/cmd/cfsslgo get -u github.com/cloudflare/cfssl/cmd/cfssljsonEine Certificate Authority (CA) initialisieren:
$ mkdir vault-ca && cd vault-caLegen Sie die CA-Dateien an:
CA-Konfigurationsdatei mit einer Gültigkeit von 5 Jahren
$ cat <<EOF > ca-config.json{ "signing": { "default": { "expiry": "8760h" }, "profiles": { "default": { "usages": ["signing", "key encipherment", "server auth", "client auth"], "expiry": "8760h" } } }}EOFCA Signing Request:
$ cat <<EOF > ca-csr.json{ "hosts": [\ "cluster.local"\ ], "key": { "algo": "rsa", "size": 2048 }, "names": [\ {\ "C": "US",\ "L": "NewYork",\ "O": "Kubernetes",\ "OU": "CA",\ "ST": "NewYork"\ }\ ]}EOFVAULT Certificate Signing Request, der von der oben angelegten CA signiert wird: Hinweis: Passen Sie den Namespace für Vault an, falls es nicht der Default-Namespace ist.
$ cat <<EOF > vault-csr.json{ "CN": "Vault-GKE", "hosts": [\ "127.0.0.1",\ "vault.default.svc.cluster.local"\ ], "key": { "algo": "rsa", "size": 2048 }, "names": [\ {\ "C": "US",\ "L": "NewYork",\ "O": "Innovia",\ "OU": "Vault",\ "ST": "NewYork"\ }\ ]}EOFDie Zertifikatsangaben unter "names" können Sie nach Belieben anpassen.
Initialisieren Sie die CA mit der eben bearbeiteten Datei:
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca2019/11/12 16:35:01 [INFO] generating a new CA key and certificate from CSR2019/11/12 16:35:01 [INFO] generate received request2019/11/12 16:35:01 [INFO] received CSR2019/11/12 16:35:01 [INFO] generating key: rsa-20482019/11/12 16:35:01 [INFO] encoded CSR2019/11/12 16:35:01 [INFO] signed certificate with serial number 425581644650417483788325060652779897454211028144Erzeugen Sie einen privaten Schlüssel und signieren Sie das TLS-Zertifikat:
$ cfssl gencert \ -ca=ca.pem \ -ca-key=ca-key.pem \ -config=ca-config.json \ -profile=default \ vault-csr.json | cfssljson -bare vault2019/11/12 16:36:33 [INFO] generate received request2019/11/12 16:36:33 [INFO] received CSR2019/11/12 16:36:33 [INFO] generating key: rsa-20482019/11/12 16:36:34 [INFO] encoded CSR2019/11/12 16:36:34 [INFO] signed certificate with serial number 311973563616303179057952194819087555625015840298Im aktuellen Arbeitsverzeichnis sollten nun folgende Dateien liegen:
ca-key.pemca.pemvault-key.pemvault.pemBewahren Sie die CA-Dateien sicher auf – Sie brauchen sie, um das Zertifikat nach Ablauf neu zu signieren (CA: 5 Jahre, Vault: 1 Jahr).
Legen Sie ein Secret für das Vault-TLS-Zertifikat und CA.pem an:
kubectl create secret generic vault-tls \ --from-file=ca.pem \ --from-file=vault.pem \ --from-file=vault-key.pemSetzen Sie das GCP-Projekt für den weiteren Verlauf:
$ export GCP_PROJECT=<your_project_id>Aktivieren Sie die für dieses Tutorial benötigten GCP-APIs:
$ gcloud services enable \ cloudapis.googleapis.com \ cloudkms.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ iam.googleapis.com \ --project ${GCP_PROJECT}Operation "operations/acf.8e126724-bbde-4c0d-b516-5dca5b8443ee" finished successfully.Vault Storage Backend
Google Cloud Storage
Im HA-Modus haben Vault-Server zwei zusätzliche Zustände: standby und active. Innerhalb eines Vault-Clusters ist nur eine einzige Instanz active und verarbeitet sämtliche Anfragen (Lese- und Schreibvorgänge); alle standby-Knoten leiten Anfragen an den active-Knoten weiter.
Legen Sie den Bucket auf GCS mit gsutil an. Bucket-Namen müssen in der gesamten Google Cloud global eindeutig sein – wählen Sie also einen einzigartigen Namen.
$ export GCS_BUCKET_NAME=mycompany-vault-data$ gsutil mb gs://$GCS_BUCKET_NAME$ gsutil versioning set on gs://$GCS_BUCKET_NAMEAuch wenn die Daten bei der Übertragung und im Ruhezustand verschlüsselt sind: Setzen Sie die Bucket-Berechtigungen restriktiv, um die Angriffsfläche klein zu halten. Sinnvoll ist ein Service Account, dessen IAM-Rechte Vaults Interaktion mit Google Cloud auf die Objekte im Storage-Bucket beschränken.
Vault Auto-Unseal

Nach einem Neustart befindet sich Vault zunächst im versiegelten und verschlüsselten Zustand. Vor der Nutzung muss es entsiegelt werden. Mit der Auto-Unseal-Funktion lassen sich Master Keys und Root-Token automatisch aus CloudKMS auslesen.
KMS-Keyring und Crypto Key anlegen:
In diesem Abschnitt legen wir das KMS-Keyring und den Schlüssel zum Ver- und Entschlüsseln der Vault-Master-Keys und des Root-Tokens an:
Das KMS-Keyring vault-helm-unseal-kr anlegen:
$ gcloud kms keyrings create vault-helm-unseal-kr \ --location global \ --project ${GCP_PROJECT}Den Verschlüsselungsschlüssel anlegen:
$ gcloud kms keys create vault-helm-unseal-key \ --location global \ --keyring vault-helm-unseal-kr \ --purpose encryption \ --project ${GCP_PROJECT}GCP Service Accounts und IAM-Berechtigungen für Vault einrichten
Variablen setzen:
$ export VAULT_SA_NAME=vault-server; export VAULT_SA=$VAULT_SA_NAME@$GCP_PROJECT.iam.gserviceaccount.comDen Vault-Server-Service-Account anlegen:
$ gcloud iam service-accounts create $VAULT_SA_NAME \ --display-name "Vault server service account" \ --project ${GCP_PROJECT}Den Service-Account-Key des Vault-Servers (Credentials-JSON-Datei) erzeugen:
$ gcloud iam service-accounts keys create \ --iam-account $VAULT_SA /tmp/vault_gcs_key.jsoncreated key [be22cfe6e30f3a3fcfc6ebaa23ca3ba905dd60ab] of type [json] as [/tmp/vault_gcs_key.json] for [[email protected]] Das Secret anlegen, in dem der Google-Service-Account von Vault hinterlegt wird$ kubectl create secret generic vault-gcs \ --from-file=/tmp/vault_gcs_key.jsonsecret/vault-gcs createdZugriff auf den GCS-Bucket des Vault-Storage gewähren:
$ gsutil iam ch \ serviceAccount:${VAULT_SA}:objectAdmin \ gs://${GCS_BUCKET_NAME}Zugriff auf den Vault-KMS-Schlüssel gewähren:
$ gcloud kms keys add-iam-policy-binding \ vault-helm-unseal-key \ --location global \ --keyring vault-helm-unseal-kr \ --member serviceAccount:${VAULT_SA} \ --role roles/cloudkms.cryptoKeyEncrypterDecrypter \ --project ${GCP_PROJECT}Updated IAM policy for key [vault-helm-unseal-key].bindings:- members: - serviceAccount:[email protected] role: roles/cloudkms.cryptoKeyEncrypterDecrypteretag: BwWZ6sIYovk=version: 1Hinweis:Falls Sie den Service Account zwischenzeitlich gelöscht und neu angelegt haben, müssen Sie die IAM-Policy auf dem Schlüssel löschen. Andernfalls springen Sie weiter zu "Das offizielle HashiCorp-Vault-Chart abrufen".$ gcloud kms keys get-iam-policy vault-helm-unseal-key --location global --keyring vault-helm-unseal-kr > kms-policy.yaml Bearbeiten Sie die Policy-Datei, entfernen Sie die Members unter binding und speichern Sie die Dateibindings:etag: BwWXQz4HjuI=version: 1Wenden Sie die Policy erneut an:
$ gcloud kms keys set-iam-policy vault-helm-unseal-key --location global --keyring vault-helm-unseal-kr kms-policy.yamlDas offizielle Vault-Chart von HashiCorp abrufen:

Hinweis:
Ab Version 0.3.0 gibt es eine Kubernetes-Vault-Integration, die Secrets automatisch in den Pod injiziert, indem sie diese als Datei in einem Volume bereitstellt. Ich empfehle dringend meinen Vault Secrets Webhook, da dieser Secrets sicherer in den Pod einschleust und gleichzeitig deren Nutzung automatisiert.
export CHART_VERSION=0.3.0Chart abrufen und entpacken:
$ wget https://github.com/hashicorp/vault-helm/archive/v$CHART_VERSION.tar.gz && tar zxf v$CHART_VERSION.tar.gz && rm v$CHART_VERSION.tar.gzDie values.yaml für das Chart konfigurieren:
Das folgende Gist enthält Platzhalter für die Variablensubstitution:
global: tlsDisable: false
server: extraEnvironmentVars: GOOGLE_APPLICATION_CREDENTIALS: /vault/userconfig/vault-gcs/vault_gcs_key.json extraVolumes: - type: secret name: vault-gcs path: "/vault/userconfig" - type: secret name: vault-tls path: "/etc/tls"
authDelegator: enabled: true
ha: enabled: true config: | ui = true listener "tcp" { tls_disable = 0 tls_cert_file = "/etc/tls/vault-tls/vault.pem" tls_key_file = "/etc/tls/vault-tls/vault-key.pem" tls_client_ca_file = "/etc/tls/vault-tls/ca.pem" tls_min_version = "tls12" address = "[::]:8200" cluster_address = "[::]:8201" } storage "gcs" { bucket = "GCS_BUCKET_NAME" ha_enabled = "true" } seal "gcpckms" { project = "GCP_PROJECT" region = "global" key_ring = "vault-helm-unseal-kr" crypto_key = "vault-helm-unseal-key" }Mit folgendem Befehl erzeugen Sie eine neue Values-Datei namens vault-gke-values.yaml:
$ curl -s https://gist.githubusercontent.com/innovia/53c05bf69312706fc93ffe3bb685b223/raw/adc169605984da8ba82082191c8f631579b1b199/vault-gke-values.yaml | sed "s/GCP_PROJECT/$GCP_PROJECT/g" | sed "s/GCS_BUCKET_NAME/$GCS_BUCKET_NAME/g" > vault-helm-$CHART_VERSION/vault-gke-values.yamlKontrollieren Sie die erzeugte Datei, um sicherzugehen, dass das richtige Projekt und der richtige GCS-Bucket eingetragen sind.
$ cat vault-helm-$CHART_VERSION/vault-gke-values.yaml | grep -E 'bucket|project'bucket = "<COMPANY>-vault-data"project = "ami-playground"Mit Helm 2.x:
Ist im Cluster kein Tiller installiert, lässt sich die Tiller-Einrichtung überspringen, indem Sie ein Tillerless-Plugin für Helm installieren. Das startet einen lokalen Tiller auf Ihrem Rechner und verweist Helm darauf. Andernfalls springen Sie weiter zum Abschnitt Vault-Chart installieren.
Das Tillerless-Helm-Plugin installieren:
Falls Helm noch nicht installiert ist:
$ brew install helm@2Nur den Client initialisieren, damit der Tiller-Server nicht installiert wird:
helm init --client-onlyhelm-tillerless-Plugin installierenhelm plugin install https://github.com/rimusz/helm-tillerTiller über Helm starten$ helm tiller startInstalled Helm version v2.16.1Copied found /usr/local/bin/tiller to helm-tiller/binHelm and Tiller are the same version!Starting Tiller...Tiller namespace: kube-systemMit Helm 3
$ brew install helmVault-Chart installieren:
Hinweis: Bei Helm 3 werden die Ressourcen in der Ausgabe nicht aufgeführt.
$ helm upgrade --install vault -f vault-helm-$CHART_VERSION/vault-gke-values.yaml vault-helm-$CHART_VERSIONrelease "vault" does not exist. Installing it now.NAME: vaultLAST DEPLOYED: Wed Nov 13 15:41:55 2019NAMESPACE: defaultSTATUS: DEPLOYEDRESOURCES:==> v1/ConfigMapNAME AGEvault-config 0s==> v1/ServiceNAME AGEvault 0s==> v1/ServiceAccountNAME AGEvault 0s==> v1/StatefulSetNAME AGEvault 0s==> v1beta1/ClusterRoleBindingNAME AGEvault-server-binding 0s==> v1beta1/PodDisruptionBudgetNAME AGEvault 0sNOTES:Thank you for installing HashiCorp Vault!Now that you have deployed Vault, you should look over the docs on usingVault with Kubernetes available here:https://www.vaultproject.io/docs/Your release is named vault. To learn more about the release, try:$ helm status vault $ helm get vaultVault sollte jetzt laufen und sich im uninitialisierten Zustand befinden.Folgende Warnungen sind OK, solange Vault noch nicht initialisiert ist:
=> Vault server started! Log data will stream in below:2019-12-17T19:07:37.937Z [INFO] proxy environment: http_proxy= https_proxy= no_proxy=2019-12-17T19:07:38.909Z [INFO] core: stored unseal keys supported, attempting fetch2019-12-17T19:07:39.037Z [WARN] failed to unseal core: error="stored unseal keys are supported, but none were found"2019-12-17T19:07:44.038Z [INFO] core: stored unseal keys supported, attempting fetch2019-12-17T19:07:44.080Z [INFO] core: autoseal: seal configuration missing, but cannot check old path as core is sealed: seal_type=recovery2019-12-17T19:07:44.174Z [WARN] failed to unseal core: error="stored unseal keys are supported, but none were found"---kubectl describe pod vault-0Events: Type Reason Age From Message ---- ------ ---- ---- ------- ... Warning Unhealthy 3s (x9 over 27s) kubelet, minikube Readiness probe failed: Key ValueVault mit KMS Auto-Unseal initialisieren
Öffnen Sie ein Port-Forward zu Vault:
$ kubectl port-forward vault-0 8200:8200 > /dev/null & export PID=$!; echo "vault port-forward pid: $PID"Verbinden Sie sich mit Vault über das CA.pem-Zertifikat:
$ export VAULT_ADDR=https://127.0.0.1:8200; export VAULT_CACERT=$PWD/ca.pemMein Vault-ca.pem liegt z. B. unter:VAULT_CACERT: /Users/ami/vault-gke-medium/ca.pemInstallieren Sie den Vault-Client (achten Sie darauf, dass Client- und Server-Version übereinstimmen):
$ brew install vaultStatus prüfen:
$ vault statusKey Value--- -----Recovery Seal Type gcpckmsInitialized falseSealed trueTotal Recovery Shares 0Threshold 0Unseal Progress 0/0Unseal Nonce n/aVersion n/aHA Enabled trueJetzt Vault initialisieren:
vault operator initRecovery Key 1: 33nCanHWgYMR/VPj6bNQdHXJiayL6WeB8Ourx4kHYNaXRecovery Key 2: IMf7RjptFxtGQUbEWUWehanCBiSY7VhElkM7rRVxczGcRecovery Key 3: zGuzk/PhNet9OHL4cW2H7d3XypDxfwWXkmajclLPklK4Recovery Key 4: nCFS0dt0cNGB2LWk0F+3Vmz9TbVNpeIsXbIXDbRarlnTRecovery Key 5: 9GxXr/6T8OJWJrWqyHQxayR0BAK+WTdbT870AzKEFl2VInitial Root Token: s.1ukhSgycySjZUJRD0bZjSEitSuccess! Vault is initializedRecovery key initialized with 5 key shares and a key threshold of 3. Pleasesecurely distribute the key shares printed above.Bewahren Sie diese Schlüssel sicher auf.
Der selbst signierten Certificate Authority vertrauen:
Da wir die ca.pem selbst erstellt haben, wird ihr nicht vertraut – sie ist nicht Teil des CA-Bundles, das mit Ihrem Rechner ausgeliefert wird.
Mit den folgenden Schritten lässt sich das je nach Betriebssystem nachholen.
macOS:
Mit "immer vertrauen" für die CA öffnen Sie die Vault-UI im Browser ohne Fehlermeldungen:
$ sudo security add-trusted-cert -d -k /Library/Keychains/System.keychain $VAULT_CACERTWindows 10:
Folgen Sie dieser Anleitung, um das Zertifikat zu den vertrauenswürdigen Herausgebern hinzuzufügen:
Kubernetes-Backend-Authentifizierung mit Vault einrichten
Da Vault läuft und hochverfügbar ist, können wir es jetzt mit Kubernetes verbinden.
Wir nutzen einen Service Account für das initiale Login von Vault gegenüber Kubernetes.
Das Token dieses Service Accounts wird per Vault-CLI in Vault konfiguriert.
Dieser Service Account verfügt über die spezielle Berechtigung "system:auth-delegator", mit der Vault den Service Account des Pods zur Authentifizierung an Kubernetes weiterreichen kann. Nach erfolgreicher Authentifizierung gibt Vault ein Vault-Login-Token an den Client zurück, der damit auf Vault zugreift und die benötigten Secrets abruft.
Der Client meldet sich mit dem Login-Token bei Vault an und holt das Secret.
Vault prüft anhand der Zuordnung von Vault-Rolle, Service Account, Namespace und Policy, ob der Zugriff erlaubt oder verweigert wird.
Legen wir den Service Account vault-reviewer dafür an:
https://gist.github.com/innovia/5435f2336e4dd0045dbb5842880b3334#file-vault-reviewer-yaml
Hinweis: Wenn Sie Vault in einem anderen Namespace eingerichtet haben, passen Sie diese Datei entsprechend an.
kubectl apply -f vault-reviewer.yamlAktivieren Sie das Kubernetes-Auth-Backend:
$ vault login$ vault auth enable kubernetesSuccess! Enabled kubernetes auth method at: kubernetes/Vault mit dem vault-reviewer-Token und der CA konfigurieren:
Hinweis: Wenn Sie Vault in einem anderen Namespace eingerichtet haben, hängen Sie das Flag -n an jeden kubectl-Befehl an.
$ VAULT_SA_TOKEN_NAME=$(kubectl get sa vault-reviewer -o jsonpath="{.secrets[*]['name']}")$ SA_JWT_TOKEN=$(kubectl get secret "$VAULT_SA_TOKEN_NAME" -o jsonpath="{.data.token}" | base64 --decode; echo)$ SA_CA_CRT=$(kubectl get secret "$VAULT_SA_TOKEN_NAME" -o jsonpath="{.data['ca\.crt']}" | base64 --decode; echo)$ vault write auth/kubernetes/config token_reviewer_jwt="$SA_JWT_TOKEN" kubernetes_host=https://kubernetes.default kubernetes_ca_cert="$SA_CA_CRT"Success! Data written to: auth/kubernetes/configGrundvoraussetzungen, damit ein Pod auf ein Secret zugreifen kann:
- Der Pod muss einen Service Account besitzen
- Das Vault-CA.pem-Secret muss im Namespace existieren, in dem der Pod läuft
- Es muss eine Policy mit mindestens Lesezugriff auf das Secret existieren
path "secret/foo" { capabilities = ["read"]}- In Vault muss eine Vault-Rolle angelegt werden:
vault write auth/kubernetes/role/<role_name> \ bound_service_account_names=<service_account_name> \ bound_service_account_namespaces=<service_account_namespace> \ policies=<policy_name>Damit ist die Einrichtung von HashiCorp Vault auf GKE abgeschlossen. Ich empfehle dringend, zusätzlich Vault Secrets Webhooks einzurichten, um Secrets aus Vault nahtlos und nur über ein paar Annotations zu konsumieren.
Vault-UI mit Identity-Aware Proxy (IAP) über einen Load Balancer einrichten

Der Identity-Aware Proxy authentifiziert Benutzer, ohne dass ein VPN oder ein SSH-Bastion-Host nötig ist.
Wenn Sie für den Service einen Load Balancer mit Identity-Aware Proxy einrichten möchten, folgen Sie den Schritten unten. Andernfalls erreichen Sie die Vault-UI über kubectl port-forward vault-0 8200.
Der folgende Prozess bindet keinen Google-Nutzer an Vault – er dient ausschließlich als Multi-Faktor-Authentifizierung. Es gäbe zwar JWT für die Vault-Authentifizierung, doch das erlaubt jedem Benutzer aus Ihrer Domain, eine Rolle zu wählen, was weniger sicher ist …
Hinweis:
Das selbst signierte Zertifikat für den Vault-Service selbst bleibt weiterhin nötig. Das Load-Balancer-Zertifikat wird benötigt, um IAP und HTTPS zu aktivieren.
Voraussetzungen:
- Für den Load Balancer muss ein Zertifikat per Google Managed Certificate erstellt oder als Kubernetes-Secret hinterlegt werden.
https://cloud.google.com/load-balancing/docs/ssl-certificates
- Die Domain muss über die Google Webmaster Tools verifiziert sein
- Es müssen eine globale statische IP sowie ein DNS-Eintrag angelegt werden
(Wenn Sie den externalDNS-Service einsetzen, entfällt das.)
$ gcloud compute addresses create vault-ui --globalEin Zertifikat lässt sich mit folgendem YAML erstellen:
https://gist.github.com/innovia/71c219692b003e97bc72feeeb5bc8442
$ kubectl apply -f managed-cert.yamlNach dem Erstellen dauert es 15–20 Minuten, bis sich der Status von Provisioning auf Active ändert.
Status des Zertifikats prüfen:
$ kubectl describe ManagedCertificate vault-ui-certificateName: vault-ui-certificateNamespace: defaultLabels: <none>Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.gke.io/v1beta1","kind":"ManagedCertificate","metadata":{"annotations":{},"name":"vault-ui-certificate","namespac...API Version: networking.gke.io/v1beta1Kind: ManagedCertificateMetadata: Creation Timestamp: 2020-01-13T23:10:28Z Generation: 3 Resource Version: 7120865 Self Link: /apis/networking.gke.io/v1beta1/namespaces/default/managedcertificates/vault-ui-certificate UID: e35e7a1b-3659-11ea-ae90-42010aa80174Spec: Domains: vault.ami-playground.doit-intl.comStatus: Certificate Name: mcrt-9462e1f4-6dd6-4cf2-8769-9693ba29789e Certificate Status: Active Domain Status: Domain: vault.ami-playground.doit-intl.com Status: Active Expire Time: 2020-04-12T15:12:29.000-07:00Events: <none>IAP für GKE konfigurieren:
Alternativ zu den hier zusammengefassten Schritten können Sie der vollständigen Anleitung folgen:
Konfigurieren Sie IAP für Ihre Domain über den OAuth-Consent-Screen und erzeugen Sie die Client-Credentials.
Kopieren Sie nach dem Erstellen die Client-ID und tragen Sie sie im Feld Authorized redirect URIs in folgendem Format ein:
https://iap.googleapis.com/v1/oauth/clientIds/<CLIENT_ID>:handleRedirectLegen Sie das Secret an, das von der Backend-Config verwendet wird:
kubectl create secret generic my-secret --from-literal=client_id=client_id_key \ --from-literal=client_secret=client_secret_keyErstellen Sie eine Backend-Config für IAP:
https://gist.github.com/innovia/4485a253f15cd824d0e6d2a19230a603
Aktivieren Sie den Abschnitt am Ende der vault-gke.yaml-Dateien und stellen Sie sicher, dass die Werte für die globale statische IP sowie der DNS-Eintrag für den Host aktualisiert sind.
Hinweis:
Sie müssen die Vault-Installation löschen und mit Helm neu erstellen, da der GKE-Ingress Probleme beim Aktualisieren bestehender Ingresses hat.
Zusammenfassung der Values-YAML-Datei:
- Wir aktivieren den Vault-UI-Service auf Port 443 und exponieren ihn über einen NodePort
- Wir koppeln den Vault-Service per Backend-Config an IAP
- Wir aktivieren den Ingress mit einer statischen globalen IP und dem darauf gemappten DNS-Host
- Wir deaktivieren HTTP auf dem Load Balancer
- Wir konfigurieren die Kommunikation zwischen Load Balancer und Vault-Pods so, dass ausschließlich HTTPS verwendet wird
- Wir richten das Managed Certificate für den Load Balancer ein, damit dieser als HTTPS-Listener arbeitet
Wenn Sie nach dem Deployment auf der IAP-Seite nachsehen, werden folgende Fehler und Warnungen angezeigt (bei Shared-VPC-Networking erscheinen unter Umständen beide Backend-Services mit ERROR. Der eigentliche Test ist der Aufruf der Vault-UI-URL im Browser):

Der erste Fehler betrifft das Default-Backend (das die 404er ausliefert). Er weist lediglich darauf hin, dass IAP für 404-Seiten nicht aktiv ist – genau so ist es gewollt.
Der andere ist nur eine Warnung. Klicken Sie darauf, sehen Sie etwa Folgendes:

Das bedeutet lediglich, dass GCP einige Firewall-Regeln erkannt hat, die IAP umgehen – etwa interne Netzwerke und die Verbindung des Load Balancers zum Vault-Backend.
Wählen Sie auf der IAP-Seite default/vault aus und fügen Sie im Info-Panel auf der linken Seite die Members hinzu, die per Load Balancer Zugriff auf die vault-ui benötigen.
Vergeben Sie an das Member die Berechtigung "IAP-secured Web App User", damit dieser Benutzer auf die Vault-UI zugreifen kann.