vault-workshop-jpに取り組んだ時の雑なメモ

Posted on
Vault

vault-workshop-jpをざっと読んだ。 Vaultに初めて入門する人のキャッチアップによさそう。取り組みながら残したメモを雑にアウトプットしておきます。

vault-overview

  • Vaultサーバを起動する
export VAULT_ADDR="http://127.0.0.1:8200"
vault server -dev
  • 別ターミナルでログイン
export VAULT_ADDR="http://127.0.0.1:8200"
vault login
  • 有効になっているSecret Engineを確認
vault secrets list
  • kvSecret Engineを使って簡単なSecretsをVaultに保存&取り出し
vault kv list secret/
vault kv put secret/mypassword password=p@ssw0rd
vault kv get secret/mypassword
  • VaultのCLIはAPIへのHTTPSアクセスをラッピングしてるに過ぎない。全てのCLIでの操作はAPIへのcurlを使ったリクエストに簡単に変換できる
    • -output-curl-stringオプションを使う
vault kv list -output-curl-string secret/
  • vault kv getする時、デフォルトはテーブル形式だが、様々なフォーマットでの出力を得られる
    • -formatオプションを使う
vault kv get -format=json secret/mypassword

Vaultの初期化処理

  • Vaultを使う時は「初期化」「Unseal」という2つのステップが必要
> vault operator init

Unseal Key 1: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Unseal Key 2: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Unseal Key 3: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Unseal Key 4: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Unseal Key 5: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Initial Root Token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • 試しにログインしてみる
    • sealedという状態なので、Root Tokenを使ってもいかなる操作も受け付けない状態
    • Unseal Keyを使ってunseal処理をおこなう
> vault login
Token (will be hidden):
Error authenticating: error looking up token: Error making API request.

URL: GET http://127.0.0.1:8200/v1/auth/token/lookup-self
Code: 503. Errors:

* error performing token check: Vault is sealed
  • デフォルトでは3回vault operator unsealしてUnseal Keyを入力すると、以下のとおりSealedステータスがfalseに変わる
> vault operator unseal
Unseal Key (will be hidden):
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false

Secret Engine: KV

  • kvSecret Engineの有効化
vault secrets enable -path=kv -version=2 kv
  • 色々なkvSecretsのいじり方
vault kv put kv/iam name=kabu password=passwd
vault kv get kv/iam
vault kv put kv/iam name=kabu-2 password=passwd
vault kv get -version=1 kv/iam

Secret Engine: Databases

特定の権限を与えたDBユーザを動的に生成・削除することができる 複数のクライアントが同じシークレット(DB接続ユーザ・パスワード)を使い回すことを防いだり、シークレットが漏れても即座に破棄するなどの運用が可能になる

  • databaseSecret Engineを有効化する
vault secrets enable -path=database database

DatabaseのDynamic Secretsの発行

流れ

  • Vaultに特権ユーザのクレデンシャルとデータベースの接続先を登録する
  • Roleを定義して、Vaultが発行するデータベースユーザの設定を行う
    • データベースに対する権限
    • TTL
  • クライアントからVaultに対してSecretsの発行を依頼する

MySQLの準備

  • ローカルマシン上でMySQLを起動
docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:5.7.22
  • rootでログインしてサンブルデータを投入
mysql> create database handson;
mysql> use handson;
mysql> create table products (id int, name varchar(50), price varchar(50));
mysql> insert into products (id, name, price) values (1, "Nice hoodie", "1580");

Vaultの設定

データベースへのConnectionの設定をおこなう Vaultはこのパラメータを使ってDBユーザを払い出すので、強権限のユーザを登録する必要がある

vault write database/config/mysql-handson-db \
  plugin_name=mysql-legacy-database-plugin \
  connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/" \
  allowed_roles="role-handson" \
  username="root" \
  password="root"
> vault list database/config
Keys
----
mysql-handson-db
 [~] [0:45:02]
> vault read database/config/mysql-handson-db
Key                                   Value
---                                   -----
allowed_roles                         [role-handson]
connection_details                    map[connection_url:{{username}}:{{password}}@tcp(127.0.0.1:3306)/ username:root]
plugin_name                           mysql-legacy-database-plugin
root_credentials_rotate_statements    []
  • Roleを定義する(Connectionの設定に対してN個のRoleを設定できる)
vault write database/roles/role-handson \
  db_name=mysql-handson-db \
  creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';" \
  default_ttl="1h" \
  max_ttl="24h"
> vault list database/roles
Keys
----
role-handson
  • /database/credsエンドポイントを使って、role-handsonというRoleに基づいたSecretを発行する
> vault read database/creds/role-handson
Key                Value
---                -----
lease_id           database/creds/role-handson/0ZEQ5RJgllfzecYd1T3HYMTB
lease_duration     1h
lease_renewable    true
password           A1a-K4iXLKlvJn4MfzM8
username           v-role-kR7sAmUTv

MySQLにアクセスして権限を試す

  • MySQLにアクセス
mysql -u <USERNAME_GEN_BY_VAULT>  -h 127.0.0.1 -p handson
mysql> use handson;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-------------------+
| Tables_in_handson |
+-------------------+
| products          |
+-------------------+
1 row in set (0.00 sec)

mysql> select * from products;
+------+-------------+-------+
| id   | name        | price |
+------+-------------+-------+
|    1 | Nice hoodie | 1580  |
+------+-------------+-------+
1 row in set (0.00 sec)

mysql> insert into products (id, name, price) values (1, "aaa", "bbb");
ERROR 1142 (42000): INSERT command denied to user 'v-role-kR7sAmUTv'@'172.17.0.1' for table 'products'
mysql> create table test (id int, name varchar(10), price varchar(10));
ERROR 1142 (42000): CREATE command denied to user 'v-role-kR7sAmUTv'@'172.17.0.1' for table 'test'

Dynamic Secretsの破棄

  • TTLによる破棄
  • rovokeによる破棄
> vault lease revoke database/creds/role-handson/0ZEQ5RJgllfzecYd1T3HYMTB
All revocation operations queued successfully!

Root Userのパスワードローテーション

  • Vaultには、Configurationとして登録したデータベースのrootユーザのパスワードをローテーションさせるAPIを持っている

  • VaultによってRootパスワードのローテーションを行ったあとは、RootのパスワードはVaultしか扱うことができない

    • そのため、通常はroot以外の特権ユーザを準備してからおこなう(Vaultが壊れた時にDBにアクセスすることができなくなる)
  • root_rotation_statementsのParameterをConfigに追加して、ローテーションのAPIが呼ばれた時に実施する処理を柄

> vault write database/config/mysql-handson-db \
  plugin_name=mysql-legacy-database-plugin \
  connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/" \
  allowed_roles="role-handson" \
  username="root" \
  password="root" \
  root_rotation_statements="SET PASSWORD = PASSWORD('{{password}}')"
  • rotate-rootのAPIを実行する
vault write -force database/rotate-root/mysql-handson-db

認証とポリシー

初めてのポリシー

  • ポリシーを管理するエンドポイントは以下の2つ

    • sys/policy
    • sys/policies
  • sys/policyの中身を見る

> vault list sys/policy
Keys
----
default
root
> vault read sys/policy/default
Key      Value
---      -----
name     default
rules    # Allow tokens to look up their own properties
path "auth/token/lookup-self" {
    capabilities = ["read"]
}
  • ポリシーの見方

    • pathと指定されているのが各エンドポイント
    • capabilitiesが各エンドポイントに対する権限
  • defaultの権限を持つトークンを発行してみる

> vault token create -policy=default
Key                  Value
---                  -----
token                s.6dvK8P8RIVu49tmSoDqdK9Ts
token_accessor       j3AKRbhLyAzUyypDoOm1cdFP
token_duration       768h
token_renewable      true
token_policies       ["default"]
identity_policies    []
policies             ["default"]

ポリシーを作る

  • vault write policyコマンドでポリシーを作成する
vault policy write my-policy my-first-policy.hcl
vault policy list
vault policy read my-policy

トークン

root token

  • Vaultが初期化された時に作成される特別なtoken
  • 他のTokenと異なり、TTLが無期限
  • Vaultでのどのオペレーションも実行可能。管理者によるVaultの最初の設定のときだけ使用して、その後に削除するべき

他のToken

  • Service token
    • Tokenに関する全ての機能が使える
    • 多機能であるが、処理は少し重い
  • Batch token
    • Vault 0.10からサポートされた新しいタイプのToken
    • 全てインメモリに保存される
    • VaultがダウンするとBatch Tokenは全て失われる
    • 非常に軽量なので、大量のリクエストへの対応やスケーラビリティに向いている