Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

GKEでVaultを高可用性構成に

By Ami MahloofDec 17, 201916 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

1 fskpg2trcdatechlv lqzw

Kubernetes標準のシークレット機能だけでは、安全な管理とは言えません。実体はBase64エンコードされた平文に過ぎず、稼働中のPodからそのまま参照できてしまいます。

免責事項:

本チュートリアルは、構築に必要な各コンポーネントを段階的に理解いただくことを目的としています。 terraform で一気に構築することももちろん可能ですが、これほど重要な基盤を中身を理解しないまま導入してしまうと、後々解決の難しいトラブルにつながりかねません。

1 3th420mk8ylbebpjutjckw

確かにKubernetesのシークレットを暗号化することは可能ですが、暗号化されるのは保管時のみです。Podにマウントされた段階ではファイルや環境変数として簡単に取り出せるため、Pod自体やkubectl経由で当該namespaceにアクセスされた場合、データが漏洩する恐れがあります。

HashiCorp Vaultは、シークレットを安全に管理し、アクセスの監査や失効も行える仕組みです。とはいえ、Vaultを導入して使うことと、そのシークレットを実際にPodで利用することは別の課題です。

本記事ではTerraformとHelmを用いてGKEにVaultをインストールする方法を扱います。Pod側でシークレットを利用する手順については、別記事「PodからVaultのシークレットを透過的に利用する方法」をご参照ください。

Vaultだけを使いたい場合や、Consul template with VaultのようなConsulの高度な機能が不要な場合には、本記事の方法のほうが管理しやすいでしょう。

本チュートリアルでは、Google Cloud Storage(GCS)をVaultのバックエンドに据え、エンドツーエンドでTLSを有効化した高可用性Vaultを構築する手順を解説します。

注意:

アップグレード時の検証や環境間の分離をしやすくするため、Vaultは環境ごとに構築することを推奨します。

Vaultをサービスとして外部公開することは推奨しません。アクセスが必要な場合は、次のコマンドで接続してください:

$ kubectl port-forward vault-0 8200:8200

そのうえで、後述のとおりhttps://127.0.0.1:8200からUIにアクセスします。

Vaultにアクセスする必要があるVMがある場合は、ServiceとPodがネイティブIPを持つためVPCピアリングを利用してください。本記事では扱いません。

チュートリアル

全体の流れ:

  • Vault用のTLS証明書を作成
  • VaultストレージバックエンドとしてGCSバケットを作成
  • Vault自動アンシール用のKMSキーリングと暗号鍵を作成
  • VaultがKMSとGCSバックエンドにアクセスするためのサービスアカウントを作成
  • HashiCorp Vault公式HelmチャートをHelm tillerless経由でインストール

Vault用TLS証明書の作成

0 y3nb5jrvforb rez

本番環境向けハードニングの推奨事項のひとつに、Vaultとクライアント間の通信を、受信・送信ともにTLSで暗号化することが挙げられます。

ここでは、次の用途で使用する証明書を作成します:

  • Kubernetes Vaultサービスのアドレス
  • 127.0.0.1

証明書の生成にはCloudFlare SSLツールキット(cfsslcfssljson)を使用します。

インストールにはGo 1.12以上の動作環境と、適切に設定されたGOPATHが必要です。

重要: GOPATHのbinがPATHに含まれているか確認してください:

export PATH=$GOPATH/bin:$PATH

CloudFlare SSLツールキットのインストール:

go get -u github.com/cloudflare/cfssl/cmd/cfssl
go get -u github.com/cloudflare/cfssl/cmd/cfssljson

認証局(CA)の初期化:

$ mkdir vault-ca && cd vault-ca

CA関連ファイルを作成します:

有効期限5年のCA設定ファイル

$ cat <<EOF > ca-config.json
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"default": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOF

CA署名リクエスト:

$ cat <<EOF > ca-csr.json
{
"hosts": [\
"cluster.local"\
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [\
{\
"C": "US",\
"L": "NewYork",\
"O": "Kubernetes",\
"OU": "CA",\
"ST": "NewYork"\
}\
]
}
EOF

上記のCAで署名するVAULT証明書署名リクエスト: 注意: Vaultをdefault以外のnamespaceで動かす場合は、namespaceを変更してください

$ 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"\
}\
]
}
EOF

もちろん、下部の「names」セクションの証明書情報は適宜変更してかまいません。

編集したファイルを使ってCAを初期化するため、次のコマンドを実行します:

$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2019/11/12 16:35:01 [INFO] generating a new CA key and certificate from CSR
2019/11/12 16:35:01 [INFO] generate received request
2019/11/12 16:35:01 [INFO] received CSR
2019/11/12 16:35:01 [INFO] generating key: rsa-2048
2019/11/12 16:35:01 [INFO] encoded CSR
2019/11/12 16:35:01 [INFO] signed certificate with serial number 425581644650417483788325060652779897454211028144

秘密鍵を作成し、TLS証明書に署名します:

$ cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=default \
vault-csr.json | cfssljson -bare vault
2019/11/12 16:36:33 [INFO] generate received request
2019/11/12 16:36:33 [INFO] received CSR
2019/11/12 16:36:33 [INFO] generating key: rsa-2048
2019/11/12 16:36:34 [INFO] encoded CSR
2019/11/12 16:36:34 [INFO] signed certificate with serial number 311973563616303179057952194819087555625015840298

ここまでで、作業ディレクトリに次のファイルが揃っているはずです:

ca-key.pem
ca.pem
vault-key.pem
vault.pem

CA関連ファイルは安全に保管してください。証明書の有効期限が切れた際の再署名に必要です(CAは5年、Vaultは1年)。

Vault TLSとca.pem用のシークレットを作成します:

kubectl create secret generic vault-tls \
--from-file=ca.pem \
--from-file=vault.pem \
--from-file=vault-key.pem

このチュートリアルで使用するGCPプロジェクトを設定します:

$ export GCP_PROJECT=<your_project_id>

本チュートリアルで必要なGCP APIを有効化:

$ 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ストレージバックエンド

0 kgo4ymq8e12mvigcGoogle Cloud Storage

HAモードで動作するVaultサーバーは、**standbyactive**という2つの状態を追加で持ちます。Vaultクラスター内では1つのインスタンスのみが_active_となり、すべてのリクエスト(読み取り・書き込み)を処理します。_standby_ノードはリクエストを_active_ノードへリダイレクトします。

gsutilコマンドでGCS上にバケットを作成しましょう。バケット名はGoogle Cloud全体で一意である必要があるため、ユニークな名前を選んでください。

$ export GCS_BUCKET_NAME=mycompany-vault-data
$ gsutil mb gs://$GCS_BUCKET_NAME
$ gsutil versioning set on gs://$GCS_BUCKET_NAME

データは転送時・保管時ともに暗号化されますが、露出を最小限に抑えるためバケットには適切な権限を設定してください。IAM権限を使い、VaultとGoogle Cloudのやり取りをこのストレージバケット内のオブジェクトに限定するサービスアカウントを作成することを推奨します。

Vault自動アンシール

0 29ts5sy8qvx7cern

Vaultは再起動するとシール状態かつ暗号化された状態で立ち上がります。利用するにはアンシールが必要ですが、CloudKMSからマスターキーとルートトークンを自動的に読み取る「自動アンシール」という新機能が使えます。

KMSキーリングと暗号鍵の作成:

このセクションでは、Vaultのマスターキーとルートトークンを暗号化・復号するためのKMSキーリングと鍵を作成します。

vault-helm-unseal-kr KMSキーリングを作成します:

$ gcloud kms keyrings create vault-helm-unseal-kr \
--location global \
--project ${GCP_PROJECT}

暗号鍵を作成します:

$ gcloud kms keys create vault-helm-unseal-key \
--location global \
--keyring vault-helm-unseal-kr \
--purpose encryption \
--project ${GCP_PROJECT}

Vault用GCPサービスアカウントとIAM権限の作成

変数を設定します:

$ export VAULT_SA_NAME=vault-server;
export VAULT_SA=$VAULT_SA_NAME@$GCP_PROJECT.iam.gserviceaccount.com

Vaultサーバー用のサービスアカウントを作成します:

$ gcloud iam service-accounts create $VAULT_SA_NAME \
--display-name "Vault server service account" \
--project ${GCP_PROJECT}

Vaultサーバー用のサービスアカウントキー(認証情報JSONファイル)を作成します:

$ gcloud iam service-accounts keys create \
--iam-account $VAULT_SA /tmp/vault_gcs_key.json
created key [be22cfe6e30f3a3fcfc6ebaa23ca3ba905dd60ab] of type [json] as [/tmp/vault_gcs_key.json] for [[email protected]]
VaultのGoogleサービスアカウントを格納するシークレットを作成
$ kubectl create secret generic vault-gcs \
--from-file=/tmp/vault_gcs_key.json
secret/vault-gcs created

VaultストレージのGCSバケットへのアクセスを付与します:

$ gsutil iam ch \
serviceAccount:${VAULT_SA}:objectAdmin \
gs://${GCS_BUCKET_NAME}

Vault KMS鍵へのアクセスを付与します:

$ 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.cryptoKeyEncrypterDecrypter
etag: BwWZ6sIYovk=
version: 1
注意:
サービスアカウントを一度削除して再作成した場合は、鍵に紐づくIAMポリシーを削除する必要があります。該当しない場合は、HashiCorp Vault公式チャートの取得セクションへ進んでください。
$ gcloud kms keys get-iam-policy vault-helm-unseal-key --location global --keyring vault-helm-unseal-kr > kms-policy.yaml
ポリシーファイルを編集し、binding配下のmembersを削除して保存
bindings:
etag: BwWXQz4HjuI=
version: 1

ポリシーを再適用します:

$ gcloud kms keys set-iam-policy vault-helm-unseal-key --location global --keyring vault-helm-unseal-kr kms-policy.yaml

HashiCorp Vault公式チャートの取得:

1 phvmhmqvoj6awvkgmrnhbg

注意:

バージョン0.3.0以降、ボリューム上にファイルとしてシークレットを展開し、Podへ自動注入するKubernetes Vault連携機能が用意されています。Podへのシークレット注入をより安全に、かつ消費の自動化まで実現したい場合は、私が公開しているvault secrets webhookの利用を強く推奨します。

export CHART_VERSION=0.3.0

チャートを取得して展開します:

$ 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.gz

チャート用values.yamlの設定:

下記のgistには、変数置換用のプレースホルダーが含まれています

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"
}

下記コマンドで_vault-gke-values.yaml_という新しいvaluesファイルを作成します

$ 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.yaml

生成されたファイルを確認し、プロジェクトとGCSバケットが正しいかチェックします。

$ cat vault-helm-$CHART_VERSION/vault-gke-values.yaml | grep -E 'bucket|project'
bucket = "<COMPANY>-vault-data"
project = "ami-playground"

helm 2.xを使う場合:

クラスターにtillerが入っていない場合は、helm用のtillerlessプラグインを導入することでtillerのセットアップを省略できます。これによりローカルマシン上でtillerを起動し、helmからそれを参照できるようになります。すでに環境がある場合は、下のVaultチャートのインストールセクションへ進んでください。

tillerless helmプラグインのインストール:

helmが未インストールの場合は、以下でインストールします

$ brew install helm@2

tillerサーバーをインストールしないよう、クライアントのみで初期化します

helm init --client-only
helm-tillerlessプラグインをインストール
helm plugin install https://github.com/rimusz/helm-tiller
helm経由でtillerを起動
$ helm tiller start
Installed Helm version v2.16.1
Copied found /usr/local/bin/tiller to helm-tiller/bin
Helm and Tiller are the same version!
Starting Tiller...
Tiller namespace: kube-system

helm 3を使う場合

$ brew install helm

Vaultチャートのインストール:

注意: helm 3を使う場合、出力にリソース一覧は表示されません。

$ helm upgrade --install vault -f vault-helm-$CHART_VERSION/vault-gke-values.yaml vault-helm-$CHART_VERSION
release "vault" does not exist. Installing it now.
NAME: vault
LAST DEPLOYED: Wed Nov 13 15:41:55 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME AGE
vault-config 0s
==> v1/Service
NAME AGE
vault 0s
==> v1/ServiceAccount
NAME AGE
vault 0s
==> v1/StatefulSet
NAME AGE
vault 0s
==> v1beta1/ClusterRoleBinding
NAME AGE
vault-server-binding 0s
==> v1beta1/PodDisruptionBudget
NAME AGE
vault 0s
NOTES:
Thank you for installing HashiCorp Vault!
Now that you have deployed Vault, you should look over the docs on using
Vault 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 vault
Vaultが起動し、未初期化状態になっているはずです。

Vaultが未初期化の段階では、以下の警告が出ても問題ありません:

=> 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 fetch
2019-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 fetch
2019-12-17T19:07:44.080Z [INFO] core: autoseal: seal configuration missing, but cannot check old path as core is sealed: seal_type=recovery
2019-12-17T19:07:44.174Z [WARN] failed to unseal core: error="stored unseal keys are supported, but none were found"
---
kubectl describe pod vault-0
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
...
Warning Unhealthy 3s (x9 over 27s) kubelet, minikube Readiness probe failed: Key Value

KMS自動アンシールでVaultを初期化

次のコマンドでVaultへのポートフォワードを開始します:

$ kubectl port-forward vault-0 8200:8200 > /dev/null & export PID=$!; echo "vault port-forward pid: $PID"

ca.pem証明書を使ってVaultに接続します

$ export VAULT_ADDR=https://127.0.0.1:8200;
export VAULT_CACERT=$PWD/ca.pem
my vault ca.pem for example is at:
VAULT_CACERT: /Users/ami/vault-gke-medium/ca.pem

Vaultクライアントをインストールします(クライアントとサーバーのバージョンを揃えてください)

$ brew install vault

ステータスを確認します:

$ vault status
Key Value
--- -----
Recovery Seal Type gcpckms
Initialized false
Sealed true
Total Recovery Shares 0
Threshold 0
Unseal Progress 0/0
Unseal Nonce n/a
Version n/a
HA Enabled true

Vaultを初期化します:

vault operator init
Recovery Key 1: 33nCanHWgYMR/VPj6bNQdHXJiayL6WeB8Ourx4kHYNaX
Recovery Key 2: IMf7RjptFxtGQUbEWUWehanCBiSY7VhElkM7rRVxczGc
Recovery Key 3: zGuzk/PhNet9OHL4cW2H7d3XypDxfwWXkmajclLPklK4
Recovery Key 4: nCFS0dt0cNGB2LWk0F+3Vmz9TbVNpeIsXbIXDbRarlnT
Recovery Key 5: 9GxXr/6T8OJWJrWqyHQxayR0BAK+WTdbT870AzKEFl2V
Initial Root Token: s.1ukhSgycySjZUJRD0bZjSEit
Success! Vault is initialized
Recovery key initialized with 5 key shares and a key threshold of 3. Please
securely distribute the key shares printed above.

これらのキーは厳重に保管してください。

自己署名認証局を信頼する:

ca.pemは自前で作成したため、OS標準のCAバンドルには含まれておらず、そのままでは信頼されません。

OSごとに次の手順で信頼を追加できます。

Mac OS:

CAを「常に信頼」に設定すると、ブラウザでVault UIをエラーなく開けるようになります:

$ sudo security add-trusted-cert -d -k /Library/Keychains/System.keychain $VAULT_CACERT

Windows 10:

下記の手順に従い、信頼された発行元に証明書を追加してください:

https://docs.microsoft.com/en-us/visualstudio/deployment/how-to-add-a-trusted-publisher-to-a-client-computer-for-clickonce-applications?view=vs-2019

VaultでKubernetesバックエンド認証を設定

Vaultの起動と高可用性化が済んだら、次はVaultとKubernetesを連携させます。

VaultからKubernetesへの初回ログインにはサービスアカウントを利用します。

このサービスアカウントのトークンは、Vault CLIを使ってVault側に登録します。

このサービスアカウントには「system:auth-delegator」という特別な権限が付与されており、これによりVaultはPodのサービスアカウントをKubernetesへ渡して認証を行えます。認証が通ると、VaultはVaultにアクセスして必要なシークレットを取得するクライアントへログイントークンを返します。

クライアントはそのログイントークンでVaultにログインし、シークレットを取得します。

Vaultは、Vaultロール・サービスアカウント・namespace・ポリシーのマッピングを照合してアクセスを許可または拒否します。

では、vault-reviewer用のサービスアカウントを作成しましょう

https://gist.github.com/innovia/5435f2336e4dd0045dbb5842880b3334#file-vault-reviewer-yaml

元のgistへのリンク

注意: Vaultを別のnamespaceで構築している場合は、このファイルも同様に更新してください。

kubectl apply -f vault-reviewer.yaml

Kubernetes認証バックエンドを有効化します:

$ vault login
$ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/

vault-reviewerトークンとCAでVaultを設定:

注意: Vaultを別のnamespaceで構築している場合は、各_kubectl_コマンドの後に_-n_フラグを付けてください

$ 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/config

Podがシークレットにアクセスするための前提条件:

  • Podにサービスアカウントが設定されていること
  • Podが動作するnamespaceにVaultのca.pemシークレットが存在すること
  • シークレットへの最低限の読み取り権限を持つポリシーが存在すること
path "secret/foo" {
capabilities = ["read"]
}
  • VaultにVaultロールが作成されていること:
vault write auth/kubernetes/role/<role_name> \
bound_service_account_names=<service_account_name> \
bound_service_account_namespaces=<service_account_namespace> \
policies=<policy_name>

以上で、GKE上のHashiCorp Vaultのセットアップは完了です。最後に、わずかなアノテーションを付けるだけでVaultからシームレスにシークレットを利用できるvault secrets webhooksの導入を強くおすすめします。

ロードバランサー経由でIdentity-Aware Proxy(IAP)付きVault UIを構築する手順

1 dxfdyie8ymjqvpgeb6gfaw

Identity-Aware Proxyは、VPNやSSH Bastionを用意することなくユーザー認証を実現する仕組みです。

IAPの詳細はこちら

Identity-Aware Proxy付きのロードバランサーを構築したい場合は、以下の手順に従ってください。それ以外の場合は、kubectl port-forward vault-0 8200でVault UIにアクセスできます。

なお、この手順はGoogleユーザーをVaultに紐付けるものではなく、あくまで多要素認証として機能します。Vault認証にJWTを使う方法もありますが、その場合はドメイン内の任意のユーザーがロールを選択できてしまうためセキュリティ面で劣ります…

注意:

Vaultサービス自体には引き続き自己署名証明書が必要です。ロードバランサー用の証明書は、IAPとhttpsを有効化するために別途必要になります。

前提条件:

  • ロードバランサー用の証明書を、Google Managed certificateで作成するか、Kubernetesシークレットとして作成しておくこと。

https://cloud.google.com/load-balancing/docs/ssl-certificates

  • ドメインがGoogle webmaster toolsで検証済みであること
  • グローバル静的IPの作成と、DNSレコードの設定が完了していること

(externalDNSサービスを利用している場合は不要です)

$ gcloud compute addresses create vault-ui --global

下記のYAMLで証明書を作成できます

https://gist.github.com/innovia/71c219692b003e97bc72feeeb5bc8442

$ kubectl apply -f managed-cert.yaml

作成後、ステータスが_Proviosning_から_Active_に変わるまで15〜20分ほど待ちます

証明書のステータスを確認します:

$ kubectl describe ManagedCertificate vault-ui-certificate
Name: vault-ui-certificate
Namespace: default
Labels: <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/v1beta1
Kind: ManagedCertificate
Metadata:
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-42010aa80174
Spec:
Domains:
vault.ami-playground.doit-intl.com
Status:
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:00
Events: <none>

GKE向けIAPの設定:

下記の要約版ではなく、公式の完全な手順に従っても構いません:

Oauth consent screenでドメインのIAPを設定し、クライアント認証情報を作成します。

クライアント作成後、クライアントIDをコピーし、承認済みリダイレクトURI欄に次の形式で追加します:

https://iap.googleapis.com/v1/oauth/clientIds/<CLIENT_ID>:handleRedirect

バックエンド設定で使うシークレットを作成します:

kubectl create secret generic my-secret --from-literal=client_id=client_id_key \
--from-literal=client_secret=client_secret_key

IAP用のバックエンド設定を作成します:

https://gist.github.com/innovia/4485a253f15cd824d0e6d2a19230a603

vault-gke.yamlの末尾セクションを有効化し、グローバル静的IPおよびホストのDNSが正しい値に更新されているか確認してください

注意:

GKE Ingressは既存Ingressの更新がうまくいかないため、一度Vaultをアンインストールしてからhelmで再作成する必要があります。

values yamlの設定内容まとめ:

  • Vault UIサービスをポート443で有効化し、NodePort経由で公開
  • バックエンド設定を介してVaultサービスにIAPを適用
  • 静的グローバルIPと、それに紐づくホストとしてDNSを指定してIngressを有効化
  • ロードバランサー上のHTTPを無効化
  • ロードバランサーとVault Pod間の通信をhttpsのみに限定
  • ロードバランサーがHTTPSリスナーとして動作するよう、マネージド証明書を設定

デプロイ後、IAPページを確認すると次のエラーや警告が表示されます(共有VPCネットワーキングを使っている場合は、両方のバックエンドサービスがERRORとなることもあります。最終的な確認はブラウザでVault UIのURLを開いて行ってください)

1 yu5axdnsw13bo 4vi sqeg

1つ目のエラーはデフォルトバックエンド(404を返すもの)に対するものです。これは404ページにIAPが適用されないことを示しているだけで、想定どおりの挙動です。

もう1つは単なる警告で、クリックすると次のような表示が出ます:

1 vulcp7of1dwxqb5m7p2zfq

これは、内部ネットワークやロードバランサーからVaultバックエンドへの通信など、IAPをバイパスするファイアウォールルールがあることをGCPが検出したという意味にすぎません。

IAPページでdefault/vaultを選択し、左側の情報パネルから、ロードバランサー経由でvault-uiにアクセスさせたいメンバーを追加します

該当ユーザーがVault UIにアクセスできるよう、メンバーには「IAP-secured Web App User」権限を付与してください。