Carpe Diem

備忘録

HashiCorp VaultのPolicyを使った運用

概要

HashiCorp VaultはPolicyを使って各APIの権限を設定します。
これによって権限を細かく設定することができますが、実際の運用ではどんな形で進めるのがいいのかがドキュメントでは分かりにくかったのでまとめした。

環境

  • Vault 0.10.3

Policy付与のフロー

以下のようにPolicyを操作できるユーザがVaultに登録し、ユーザなどにマッピングします。

f:id:quoll00:20180711161948p:plain

ref: Policies - Vault by HashiCorp

ユーザにマッピングした場合、そのユーザがログインしてトークンを発行する時にそのPolicyが付与されます。

f:id:quoll00:20180711162114p:plain

ref: Policies - Vault by HashiCorp

Policyの作成

ではPolicyを作成します。Vaultはデフォルトでは全権限がdeny扱いになっているので、whitelist形式で権限を付与していきます。

admin policyの作成

Policies | Vault - HashiCorp Learn

こちらのガイドのadminをそのまま使っています。

admin.hcl

# Manage auth methods broadly across Vault
path "auth/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# List, create, update, and delete auth methods
path "sys/auth/*"
{
  capabilities = ["create", "read", "update", "delete", "sudo"]
}

# List existing policies
path "sys/policy"
{
  capabilities = ["read"]
}

# Create and manage ACL policies broadly across Vault
path "sys/policy/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# List, create, update, and delete key/value secrets
path "secret/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Manage and manage secret engines broadly across Vault.
path "sys/mounts/*"
{
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Read health checks
path "sys/health"
{
  capabilities = ["read", "sudo"]
}

ポイントとなるのは

  • 基本的なコマンドの権限が揃っている
  • policyを自分で変更できるので、新しい機能もpolicyの更新で対応できる

という点です。

作成

vault serverにpolicyを登録します。最初の図の3. Upload Policy to Vaultです。

$ vault policy write admin admin.hcl 

ssh policyの作成

christina04.hatenablog.com

の設定をできるssh-admin.hclというPolicyと、それを使って証明書の発行だけできるssh-user.hclというPolicyを用意します。

ssh-admin.hcl

設定用のwrite権限を付与します。

# Manage ssh ca config broadly across Vault
path "ssh-client-signer/config/*"
{
  capabilities = ["create", "read", "update", "delete", "sudo"]
}

# List all ssh roles
path "ssh-client-signer/roles/"
{
  capabilities = ["list"]
}

# Manage ssh roles broadly across Vault
path "ssh-client-signer/roles/*"
{
  capabilities = ["create", "read", "update", "delete", "sudo"]
}

# Write ssh certificates
path "ssh-client-signer/sign/*"
{
  capabilities = ["update"]
}

In other words, policy paths targeting list capability should end with a trailing slash:

ref: Policies - Vault by HashiCorp

とあるように、list権限は最後のslashが必要なので注意してください。

ssh-user.hcl

証明書の発行は以下の権限があれば可能です。

# Write ssh certificates
path "ssh-client-signer/sign/*"
{
  capabilities = ["update"]
}

作成

vault serverにpolicyを登録します。

$ vault policy write ssh-admin ssh-admin.hcl 
$ vault policy write ssh-user ssh-user.hcl 

ユーザの作成

簡単のためUserpass Auth Methodを使います。

$ vault auth enable userpass

先程作ったpolicyを用いてユーザに権限を付与して作成します。 最初の図の4. Map Authentication Data to Policyです。

$ vault write auth/userpass/users/jun06t \
    password=foo \
    policies=ssh-user

ログイン

$ vault login -method=userpass \
    username=jun06t
Password (will be hidden): 

Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                    Value
---                    -----
token                  e8ac3d16-6652-e915-4041-b6623835ee1e
token_accessor         fb4206e4-4fe0-764f-6cc5-40b0e2f156ae
token_duration         768h
token_renewable        true
token_policies         ["ssh-user" "default"]
identity_policies      []
policies               ["ssh-user" "default"]
token_meta_username    jun06t

無事ログインできました。
policies["ssh-user" "default"]とちゃんと権限も付与されてます。

権限確認

ssh権限

sshで証明書が発行できるか試します。

vault write ssh-client-signer/sign/my-role \
    public_key=@$HOME/.ssh/id_rsa.pub

Key              Value
---              -----
serial_number    ec032c580f35fa8a
signed_key       ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2Et...

できました!

admin権限

adminなら持っているauth系メソッドを使ってみます。

$ vault auth enable userpass
Error enabling userpass auth: Error making API request.

URL: POST http://10.74.200.152:8200/v1/sys/auth/userpass
Code: 403. Errors:

* permission denied

ちゃんと怒られました。マッピングしたPolicy通りですね。

注意点

ログイン時に生成されたトークンですが、例えばssh-userPolicyが付与されたとして後からこのユーザに別の権限を追加したいと思った時に

  1. 新しいPolicyを追加でマッピングする
  2. 既存のPolicyを更新する

によって挙動が違います。

a. 新しいPolicyを追加でユーザにマッピングする

この場合、過去に発行されたトークンにはそのPolicyは付与されてないので、その権限は反映されません
また逆に言えば、過去にマッピングしたPolicyをマッピングから削除しても、トークンの期限までその権限は使えます。

反映するためには再ログインしてトークンを再発行する必要があります。

b. 既存のPolicyを更新する

この場合は再ログインしてトークン更新しなくてもしなくても権限が反映されます。 トークンに付与されたPolicyはAPIコールの度にvault内で毎回参照してくれるようです。

root token

Vaultのドキュメントではadmin policyを持ったユーザを作成後はroot policyを持ったtokenを削除するよう奨めています。

In fact, the Vault team recommends that root tokens are only used for just enough initial setup (usually, setting up auth methods and policies necessary to allow administrators to acquire more limited tokens) or in emergencies, and are revoked immediately after they are no longer needed.

ref: Tokens - Vault by HashiCorp

root tokenの削除

revokeコマンドで削除します。

$ vault token revoke 96ddf4bc-d217-f3ba-f9bd-017055595017
Success! Revoked token (if it existed)

以降はそのtokenではvaultを使えなくなります。

$ vault token lookup 96ddf4bc-d217-f3ba-f9bd-017055595017
Error looking up token: Error making API request.

URL: POST http://localhost:8200/v1/auth/token/lookup
Code: 403. Errors:

* bad token

root tokenの再発行

でもroot tokenで操作したくなるケースは起きうるかと思います。
もちろんそのケースを想定して、vaultではroot tokenを再発行するコマンドがあります。

Generate Root Tokens Using Unseal Keys | Vault - HashiCorp Learn

これにはunseal keysが必要になります。
またOTP(ワンタイムパスワード)を使うか、PGPを使うかの2つ選択肢があります。

OTPを使った再発行

OTPを使って再発行する方法です。

$ vault operator generate-root -generate-otp
s7/IVYwzC3hpKNgP6bdziQ==

発行されたOTPを指定してinitializeを実行します。

$ vault operator generate-root -init -otp=s7/IVYwzC3hpKNgP6bdziQ==
Nonce       c50a52be-8444-dabd-4a30-a162268a18c6
Started     true
Progress    0/3
Complete    false

次にgenerate-rootをするとunseal keyを入力するようになります。

$ vault operator generate-root
Root generation operation nonce: c50a52be-8444-dabd-4a30-a162268a18c6
Unseal Key (will be hidden): 
Nonce       c50a52be-8444-dabd-4a30-a162268a18c6
Started     true
Progress    1/3
Complete    false

$ vault operator generate-root
Root generation operation nonce: c50a52be-8444-dabd-4a30-a162268a18c6
Unseal Key (will be hidden): 
Nonce       c50a52be-8444-dabd-4a30-a162268a18c6
Started     true
Progress    2/3
Complete    false

$ vault operator generate-root
Root generation operation nonce: c50a52be-8444-dabd-4a30-a162268a18c6
Unseal Key (will be hidden): 
Nonce         c50a52be-8444-dabd-4a30-a162268a18c6
Started       true
Progress      3/3
Complete      true
Root Token    7Mtpg2sw3d0gjQWEF3c2aQ==

unseal keyの入力が終わると、暗号化されたroot tokenが生成されます。

root tokenの復号化

OTPを使って復号します。

$ vault operator generate-root \
    -decode=7Mtpg2sw3d0gjQWEF3c2aQ== \
    -otp=s7/IVYwzC3hpKNgP6bdziQ==

5f74a1d6-e703-d6a5-49a5-dd8bfec045e0

これでroot tokenが再発行されました。

lookupするとroot policyであることが分かります。

$ vault token lookup 5f74a1d6-e703-d6a5-49a5-dd8bfec045e0
Key                 Value
---                 -----
accessor            2b001d9d-419a-504c-3bd3-3fabd4247413
creation_time       1531291302
creation_ttl        0
display_name        root
entity_id           n/a
expire_time         <nil>
explicit_max_ttl    0
id                  5f74a1d6-e703-d6a5-49a5-dd8bfec045e0
meta                <nil>
num_uses            0
orphan              true
path                auth/token/root
policies            [root]
ttl                 0

その他

$ vault policy fmt xxx.hcl

でPolicyファイルのフォーマットもできます。

まとめ

VaultでのPolicy運用についてまとめました。
policyを操作できるadminpolicyは実質rootと同じですが、

  • 認証のあるユーザとマッピングできること
  • 発行されるトークンに期限があること
  • 新しい機能はpolicyの更新が必要なため、なんでも自由に使えるわけではないこと

といった制限が入ることでrootよりもセキュアに管理できるようになります。

ソース