2019年6月13日木曜日

【Hashicorp】Vault を試してみた

概要

Vault (ボールト) はパスワードや認証キーなどのセンシティブなデータを暗号化して管理するためのツールです
登録したパスワードなどは API や CLI を使って取得したり更新したりすることができます
今回は Mac 上でインストールし公式の GettingStarted をやってみました

環境

  • macOS 10.14.5
  • vault 1.1.3

インストール

Mac の場合 Homebrew でインストール可能です
ダウンロードページからバイナリをダウンロードして PATH 上に配置しても OK です

  • brew install vault

サーバ起動

開発モード (-dev) で Vault サーバを起動しましょう

  • vault server -dev

フォアグラウンドで動作するので別ターミナルを開いて操作してみます

クライアント設定

Vault サーバの情報を環境変数に設定します
先程サーバを起動した際にアドレスの情報と Root Token の情報が標準出力に表示されいてるのでそれを使ってください

  • export VAULT_ADDR='http://127.0.0.1:8200'
  • export VAULT_DEV_ROOT_TOKEN_ID='s.ClxVsF2FBJPRZSqE5DT1flZa'

status コマンドを叩いて問題なければサーバにアクセスできています

  • vault status
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    1
Threshold       1
Version         1.1.3
Cluster Name    vault-cluster-8a3a8aeb
Cluster ID      832c632e-de9c-ca66-af9a-610f573f35c8
HA Enabled      false

基本操作

まずは Vault に対して基本操作をしてみます

登録してみる

kv put コマンドを使います
シークレットを保存するパスと key=value 形式でシークレットを指定します

  • vault kv put secret/hello foo=world
Key              Value
---              -----
created_time     2019-06-09T23:28:16.494828Z
deletion_time    n/a
destroyed        false
version          1

シークレットを保存する場合はファイルまたは標準入力から読み込むことを推奨しています
理由としてはコマンドで実行した場合 bash などの履歴に残るため平文のパスワードなどが確認できてしまう恐れがあるためです

  • vault kv put secret/hello foo=world excited=yes
Key              Value
---              -----
created_time     2019-06-09T23:29:17.718256Z
deletion_time    n/a
destroyed        false
version          2

既存のパスに対して再度 put すると上書きされます
また key=value 情報を追加することもできます

取得する

kv get を使います
引数にパスを指定すれば取得できます

  • vault kv get secret/hello
====== Metadata ======
Key              Value
---              -----
created_time     2019-06-09T23:29:17.718256Z
deletion_time    n/a
destroyed        false
version          2

===== Data =====
Key        Value
---        -----
excited    yes
foo        world

-format=json を指定すれば JSON 形式で取得できます

  • vault kv get -format=json secret/hello

削除する

kv delete コマンドを使います

  • vault kv delete secret/hello

Success! Data deleted (if it existed) at: secret/hello

これで登録した key=value のシークレットデータは削除されますが secret/hello のパスは残っています

シークレットエンジンとパス

Vault はシークレットエンジンと呼ばれる key=value を保存する機能を持っています
シークレットエンジンには様々な種類がありどのシークレットエンジンにアクセスするかをパスで判断しています
例えばこれまで使ってきたシークレットエンジンは「kv」で kv シークレットエンジンにアクセスするには secret/ にアクセスする必要があります
公式ではこのような機能は VFS (Virtual File System) に似ていると説明しています

Vault は AWS の IAM をシークレットエンジンにすることもできます
IAM をシークレットエンジンは aws という名前で定義されています

シークレットエンジンとパスはデフォルトで決まっていますが自分で定義することもできます
例えば kv シークレットエンジンを secret/ ではなく kv/ でアクセスできるようにするには secrets enable コマンドを使います

  • vault secrets enable -path=kv kv

=> Success! Enabled the kv secrets engine at: kv/

これで kv/ にアクセスしても kv エンジンを使えます
ただしシークレットエンジンは同じであっても secret/ に保存したシークレットを kv/ からアクセスできるわけではないので注意してください
あくまでも別のパスを追加するだけです

シークレットエンジンとパスの組み合わせは secrets list コマンドを使います

  • vault secrets list
Path          Type         Accessor              Description
----          ----         --------              -----------
cubbyhole/    cubbyhole    cubbyhole_03e682aa    per-token private secret storage
identity/     identity     identity_364f85b0     identity store
kv/           kv           kv_f77a9201           n/a
secret/       kv           kv_0f47c39e           key/value secret storage
sys/          system       system_dca27662       system endpoints used for control, policy and debugging

新しいパスを使ってデータを登録してみましょう

$ vault write kv/my-secret value="s3c(eT"
Success! Data written to: kv/my-secret
$ vault write kv/hello target=world
Success! Data written to: kv/hello
$ vault write kv/airplane type=boeing class=787
Success! Data written to: kv/airplane
$ vault list kv
Keys
----
airplane
hello
my-secret

こんな感じでアクセスできます
冒頭で登録した secret/hello は表示されていないことも確認できます

有効にしたパスは当然無効にすることもできます

  • vault secrets disable kv/

=> Success! Disabled the secrets engine (if it existed) at: kv/

putwrite, get ができなくなると思います
また secrets list にも表示されなくなります
一度 disable にしたパスを再度 enable にしても前のシークレットデータは戻らないので注意してください

ダイナミックシークレット

簡単に言えばアクセスしたときに初めてシークレットエンジンが生成される仕組みです
ダイナミックシークレットは使わない時にはアクセス不可にできるので不正アクセスの防止を行うことができます
ダイナミックシークレットを試すには aws シークレットエンジンを使います
AWS のアカウントが必要になるので事前に準備しておきましょう (ちなみにお金のかかるリソースは使わないので安心してください)

まずは aws シークレットエンジンを有効にします

  • vault secrets enable -path=aws aws

次に AWS で作成したアクセスキーとシークレットキーを登録します

  • vault write aws/config/root access_key=xxxxxxxxxxxxxxxxxxx secret_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx region=us-east-2

Vault から IAM にユーザを作成した際のデフォルトポリシーを登録します
今回はサンプルなのでフルアクセスのポリシーになっていますがここは適宜用途に合わせて変更してください
credential_type には他に federation_tokenassumed_role が指定できますが今回は使いません

vault write aws/roles/my-role \
credential_type=iam_user \
policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1426528957000",
      "Effect": "Allow",
      "Action": [
        "ec2:*"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
EOF

作成したポリシーは read で確認できます

  • vault read aws/roles/my-role

ではこれでシークレットを登録してみます
read すると同時に AWS の IAM 側にユーザが作成されると思います

  • vault read aws/creds/my-role
Key                Value
---                -----
lease_id           aws/creds/my-role/LDOIOt4aBN2f1SiGUdtIl5Qj
lease_duration     768h
lease_renewable    true
access_key         AKIAQ4627A5STJ445PF7
secret_key         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
security_token     <nil>

コンソールで確認するとユーザが存在するのが確認できると思います

ロールも Vault に登録されたものが設定されています

ダイナミックシークレットを削除するには lease revoke コマンドを使います

  • vault lease revoke aws/creds/my-role/LDOIOt4aBN2f1SiGUdtIl5Qj

これで IAM からもユーザが削除されます
削除時に指定している ID は lease_id で呼ばれ Vault 内部で管理されています

パスヘルプ

aws シークレットエンジンに触れましたが他にもアクセスできるパスはあります
確認するには path-help というコマンドがあるのでこれを使うとどこにアクセスすればいいかわかります

  • vault path-help aws

認証

Vault にログインするためのセッショントークンを発行することができます
これまで Vault にアクセスできたのは vault server -dev でサーバを起動した際にトークンが発行されておりそれを使っているためです
機能確認のため別のトークンを発行してみます

  • vault token create
Key                  Value
---                  -----
token                s.M7sqaUReQRKX8fM3P0l1HceU
token_accessor       2WcqgKcNieednDvsqIhOnXOe
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]

これで別のトークンが発行されました
テストなのでポリシーは「root」を使っています
このトークンを使ってログインしてみます

  • vault login s.M7sqaUReQRKX8fM3P0l1HceU
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                s.M7sqaUReQRKX8fM3P0l1HceU
token_accessor       2WcqgKcNieednDvsqIhOnXOe
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]

次回からのアクセスは自動的にこのトークンが使われるようになります
ではこのトークンは無効にしてみます

  • vault token revoke s.M7sqaUReQRKX8fM3P0l1HceU

=> Success! Revoked token (if it existed)

するとこれまでアクセスできたコマンドがアクセスできなくなっていると思います

  • vault token create
Error creating token: Error making API request.

URL: POST http://127.0.0.1:8200/v1/auth/token/create
Code: 403. Errors:

* permission denied

こんな感じでトークンを発行し認証をコントロールすることができます
次も作業するので環境変数 (VAULT_DEV_ROOT_TOKEN_ID) に設定したトークンを使ってログインし直しましょう

  • vault login $VAULT_DEV_ROOT_TOKEN_ID
  • vault token lookup

Vault はトークンを発行するのにサードパーティの認証を使うこともできます
例えば Github と連携し Github のアクセストークンを使うことで Vault 用のトークンを発行することもできます
※少し調べた感じだと Github Authentication は Organization への所属が必要っぽかったので試せませんでした

ポリシー

Vault でトークンを発行した際にそのトークンに割り当てるポリシーを設定することができます
ポリシーはアクセス可能なパス (シークレットエンジン) を HCL と呼ばれるフォーマットで定義します
例えば「このトークンは secret/ にはアクセスできるけど aws/ にはアクセスできない」というポリシーが作れます

ポリシーは HCL というフォーマットで記載します
簡単なポリシーを作成してみましょう

  • vim default2.hcl
path "secret/data/*" {
  capabilities = ["create", "update"]
}
path "secret/data/foo" {
  capabilities = ["read"]
}

書き換えたら新規でポリシーを登録します

  • vault policy write default2 default2.hcl

=> Success! Uploaded policy: default2

念の為確認しましょう

  • vault policy list
default
default2
root

トークンを新規で発行して動作確認してみます

  • vault token create -policy=default2
Key                  Value
---                  -----
token                s.gSmVv0dNHduln7CSmrAdKxeK
token_accessor       mXam7tDGjChxxdROT8PuP01F
token_duration       768h
token_renewable      true
token_policies       ["default" "default2"]
identity_policies    []
policies             ["default" "default2"]
  • vault login s.gSmVv0dNHduln7CSmrAdKxeK

これで使用するトークンが default2 のポリシーが割り当てたものに変わりました
ポリシー通りに動作するか確認します

  • vault kv put secret/bar key=value
Key              Value
---              -----
created_time     2019-06-10T05:36:51.687562Z
deletion_time    n/a
destroyed        false
version          1
  • vault kv get secret/bar
Error reading secret/data/bar: Error making API request.

URL: GET http://127.0.0.1:8200/v1/secret/data/bar
Code: 403. Errors:

* 1 error occurred:
        * permission denied

secret/bar に登録はできますが読み込みができないのがわかります
secret/foo は読み込みだけできます

HTTP API

これまでは CLI でシークレットエンジンにアクセスしましたが HTTP API を直接コールしてアクセスすることもできます
またアクセスする API は v2 になるので注意してください

登録

  • curl -XPOST -H "X-Vault-Token: $VAULT_DEV_ROOT_TOKEN_ID" -d '{"data":{"excited":"yes","foo":"world"}}' http://127.0.0.1:8200/v1/secret/data/hello

取得

  • curl -XGET -H "X-Vault-Token: $VAULT_DEV_ROOT_TOKEN_ID" http://127.0.0.1:8200/v1/secret/data/hello

一覧

  • curl -XLIST -H "X-Vault-Token: $VAULT_DEV_ROOT_TOKEN_ID" http://127.0.0.1:8200/v1/secret/metadata

削除

  • curl -XDELETE -H "X-Vault-Token: $VAULT_DEV_ROOT_TOKEN_ID" http://127.0.0.1:8200/v1/secret/data/hello

おまけ: 管理画面

http://127.0.0.1:8200/ui にアクセスすると Vault の管理画面が使えます
ただ Homebrew からインストールしたバイナリだと UI なし版になっているので公式からダウンロードしたバイナリと入れ替える必要があります

  • cd /usr/local/Cellar/vault/1.1.3/bin/
  • wget 'https://releases.hashicorp.com/vault/1.1.3/vault_1.1.3_darwin_amd64.zip'
  • unzip vault_1.1.3_darwin_amd64.zip

これで再度 vault を起動しましょう

  • vault server -dev

そして http://127.0.0.1:8200/ui/ にアクセスしてみましょう
トークンでログインしましょう
トークンは VAULT_DEV_ROOT_TOKEN_ID に設定したトークンで OK です
vault を再起動している場合は新しいトークンになっているので標準出力を確認してください
わからない場合は vault token lookup で確認できます

ログインするとシークレットエンジンの一覧が表示されます
ここからシークレットエンジンの有効化や認証の追加もできます
コマンドや API でオペレーションせずに UI でいろいろと操作できます

最後に

Vault を Mac 上にインストールして試してみました
シークレット情報を登録し CLI や API で簡単に取得することができます
またシークレットを登録するバックエンドには AWS や Google などを指定することも可能だということがわかりました

GettingStarted では今回紹介した内容以外に「Github を使った認証」「プロダクション向けのデプロイ方法」があります
今回は長くなりそうだったので飛ばしているので興味があればやってみてください

参考サイト

0 件のコメント:

コメントを投稿