GCP Auth MethodではGCPのIAM Service Account
, Google Compute Engine Instances
を利用してクライアントを認証することができます。
Service Account
はIAM Service Accountを利用しての認証Google Compute Engine Instances
はGCEインスタンスのメタデータを利用して認証
このハンズオンではGCPアカウントが必要です。こちらからアカウントを作成していください。
まずはVault上のデータとポリシーを準備します。Root Tokenでログインし、以下のコマンドを実行してください。
$ vault kv put kv/cred-1 name=user-1 password=passwd
$ vault kv put kv/cred-2 name=user-2 password=dwssap
次にポリシーを作成します。
$ vault policy write read-cred-1 -<<EOF
path "kv/cred-1" {
capabilities = [ "read" ]
}
EOF
このポリシーは後ほどクライアントが利用するGCP Service Accountとの紐付けを行い、GCP Authでログインしたユーザに与えるVaultの権限になります。
ここではKV Secret Engine
のkv/cred-1
のreadのみ出来る権限として設定しています。
GCP側の設定です。
まず、トップ画面の検索ボックスからIAM Service Account Credentials API
と検索しEnable
をクリックしてAPIを有効化します。
次にGCPを使って認証をするためにVault側に設定するService Accountの発行です。Vaultはこのシークレットを利用してGCPへ認証を依頼します。
GCPのコンソールにログインして、Navigation Menu
からIAM&Admin
-> Service accounts
と進んでください。
CREATE SERVICE ACCOUNT
をクリックして、名前にvault-server
と入力してロールの選択に移ります。
Compute Viewer
Service Account Key Admin
の二つを選択し、CREATE
してください。
CONTIUNE
で進んだら、CREATE KEY
でJSONのキーを発行します。ダウンロードされたキーは.gcp-vault-auth-config-key.json
にリネームします。
$ mv /path/to/***********.json ~/.gcp-vault-auth-config-key.json
次にVaultにログインするクライアント側のService Accountを発行します。
GCPのコンソールにログインして、Navigation Menu
からIAM&Admin
-> Service accounts
と進んでください。
CREATE SERVICE ACCOUNT
をクリックして、名前にvault-client
と入力してロールの選択に移ります。
Service Account Token Creator
を選択し、CREATE
してください。
CONTIUNE
で進んだら、CREATE KEY
でJSONのキーを発行します。ダウンロードされたキーは.gcp-vault-client-key.json
にリネームします。
$ mv /path/to/***********.json ~/.gcp-vault-client-key.json
これでGCP側の準備は完了です。
こちらがワークフローです。
最後にGCP Auth Method
の設定を行います。
GCP認証を有効化し、Vault用のService Accountをセットします。VaultはこのService Accountを利用してGCPへ認証を依頼します。
$ vault auth enable gcp
$ vault write auth/gcp/config credentials=@.gcp-vault-auth-config-key.json
role
を作成します。read-cred-1
のポリシーを先ほど発行したService Accountにバインドします。これでこのService Accountを使ってログインしたユーザにread-cred-1
で設定したVaultの権限を与えることができます。
GCP_PRJ
にご自身のGCPプロジェクト名をセットしてください。
$ GCP_PRJ=se-kabu
$ vault write auth/gcp/role/read-cred \
type="iam" \
policies="read-cred-1" \
bound_service_accounts="vault-client@${GCP_PRJ}.iam.gserviceaccount.com"
これで設定は完了です。ログインしてみましょう。ログインには
- CLI Helperを使って認証に必要なJWTを取得してVaultにリクエストする(IAMのみ有効)
- CLI使って別で生成したJWTを使ってリクエストする
- APIを実行する
の3パターンがあります。今回はCLI Helperを使ってみます。
$ vault login -method=gcp \
role="read-cred" \
service_account="vault-client@${GCP_PRJ}.iam.gserviceaccount.com" \
project="${GCP_PRJ}" \
jwt_exp="15m" \
credentials=@.gcp-vault-client.key.json
これでログインができました。以降のリクエストはここで発行されたトークンを使って実行されます。トークンの権限を試してみましょう。
$ vault kv get kv/cred-1
====== Data ======
Key Value
--- -----
name user-1
password passwd
$ vault kv get kv/cred-2
Error reading kv/cred-2: Error making API request.
URL: GET http://127.0.0.1:8200/v1/kv/cred-2
Code: 403. Errors:
* 1 error occurred:
* permission denied
ロールとポリシーで設定したように今回作成したService Accountではkv/cred-1
をreadするためのポリシーがバインドされているため設定通りに動作していることがわかります。
次にGCEのメタデータを利用して認証するパターンを試してみます。
手順の前に以下のGCEインスタンスを立ち上げてください。
- Service Account:
vault-client
- Zone:
asia-northeast1-b
- Label:
foo:bar
- SSHログインが有効
- curlコマンドが利用可能
- インターネットアクセス可能
GCEインスタンスが立ち上がったら、Vault側の設定を加えます。まずはRoot Tokenでログインし直してください。
$ vault login
次にGCE認証用のロールを定義します。
$ ZONES=asia-northeast1-b
$ LABELS=foo:bar
$ vault write auth/gcp/role/read-cred-gce \
type="gce" \
policies="read-cred-1" \
bound_projects=${GCP_PRJ} \
bound_zones=${ZONES} \
bound_labels=${LABELS}
先ほどはService Accountで認証しましたが、今回はGCEのメタデータを利用します。その他にも以下のメタデータをセットできます。
- GCEインスタンスに付与される
Service Account
Instance Group
Region
各パラメタータをリスト型で設定できるため複数の値を入れることもできます。
これでVault側の設定は完了です。
次にGCEインスタンスにSSHで入り、次のコマンドを実行してください。
$ ROLE=read-cred-gce
$ curl \
--header "Metadata-Flavor: Google" \
--get \
--data-urlencode "audience=http://vault/${ROLE}" \
--data-urlencode "format=full" \
"http://metadata/computeMetadata/v1/instance/service-accounts/default/identity"
インスタンスのメタデータサーバからJWTの発行を依頼しています。これはGCEインスタンス上からのみ有効なリクエストです。
発行されたJWTをコピーしてローカルの端末に戻ります。先ほど発行されたJWTを使ってログインしてみましょう。(今回はVaultがローカルマシンで起動している前提のためローカルから実行しますが、通常はGCEからリーチできる所に配置しGCEインスタンスから利用します。)
こちらのワークフローがわかりやすいです。(refer: https://petersouter.xyz/demonstrating-the-gce-auth-method-for-vault/)
$ JWT=<COPIED_TOKEN>
$ VTOKEN=$(vault write -field=token auth/gcp/login \
role="read-cred-gce" \
jwt=${JWT})
$ echo ${VTOKEN}
トークンが発行されたはずです。
$ vault token lookup ${VTOKEN}
Key Value
--- -----
accessor 29wEzEdQ3O3yxgDXqzAfKD8G
creation_time 1591159208
creation_ttl 768h
display_name gcp-terraform
entity_id 796c99f7-718c-1023-69fb-1da9da0b0f01
expire_time 2020-07-05T13:40:08.801533+09:00
explicit_max_ttl 0s
id s.uwhaAkaS9A7C2FVAGOIe1SKA
issue_time 2020-06-03T13:40:08.801538+09:00
meta map[instance_creation_timestamp:1591159129 instance_id:6418544221929256035 instance_name:terraform project_id:se-kabu project_number:707116064532 role:read-cred-gce service_account_email:vault-client@se-kabu.iam.gserviceaccount.com service_account_id:101585660406385936575 zone:asia-northeast1-b]
num_uses 0
orphan true
path auth/gcp/login
policies [default read-cred-1]
renewable true
ttl 767h59m50s
type service
read-cred-1
のポリシーが付与されていることがわかるでしょう。
このトークンを使ってログインして先ほどと同様にテストしてみます。
$ vault login ${VTOKEN}
$ vault kv get kv/cred-1
====== Data ======
Key Value
--- -----
name user-1
password passwd
$ vault kv get kv/cred-2
Error reading kv/cred-2: Error making API request.
URL: GET http://127.0.0.1:8200/v1/kv/cred-2
Code: 403. Errors:
* 1 error occurred:
* permission denied
設定した通りの権限となっているでしょう。
このようにGCEインスタンスがGCE Metadata Server
と連携をしSigned JWTを取得し、それを利用してVaultの認証することができます。
これを利用することでGCEインスタンスのメタ情報をもとにGCEインスタンスにVaultのアクセス権限を付与することが可能です。