AnsibleでHashiCorp Vaultに登録した機密情報を使用する
HashiCorp Vault(以下 vault)を利用してパスワードなどの機密情報を保存し、それを Ansible で利用してみました。
検証環境
- Ubuntu on WSL2
$ uname -a
Linux ryzen5pc 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.4 LTS"
セットアップ
ワークスペース
~/hashicorp-vault-ansible
というディレクトリで作業することにします。
1$ mkdir ~/hashicorp-vault-ansible
vault のインストール
vault はバイナリをダウンロードして利用するか、各 OS 向けのパッケージマネージャでインストールすることができます。
今回はバイナリをダウンロードしました。
- ドキュメント Install Vault
1$ cd ~/hashicorp-vault-ansible
2$ curl -O https://releases.hashicorp.com/vault/1.11.0/vault_1.11.0_linux_amd64.zip
3$ unzip vault_1.11.0_linux_amd64.zip
4$ ./vault version
5Vault v1.11.0 (ea296ccf58507b25051bc0597379c467046eb2f1), built 2022-06-17T15:48:44Z
ansible のインストール
pipenv で python をインストールしつつ、pip で ansible をインストールします。
1$ sudo apt update
2$ sudo apt install pipenv
3$ pipenv --python 3
4$ pipenv shell
5
6$ pip install ansible
ansible で vault のデータを扱うためのセットアップ
community.hashi_vaultという collection を利用します。
1$ pip install hvac
2$ ansible-galaxy collection install community.hashi_vault
vault を起動する
以下のコマンドで vault dev server を起動できます
1$ vault server -dev
2==> Vault server configuration:
3
4 Api Address: http://127.0.0.1:8200
5 Cgo: disabled
6 Cluster Address: https://127.0.0.1:8201
7 Go Version: go1.17.11
8 Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
9 Log Level: info
10 Mlock: supported: true, enabled: false
11 Recovery Mode: false
12 Storage: inmem
13 Version: Vault v1.11.0, built 2022-06-17T15:48:44Z
14 Version Sha: ea296ccf58507b25051bc0597379c467046eb2f1
15
16==> Vault server started! Log data will stream in below:
Api Address (http://127.0.0.1:8200/)にブラウザでアクセスするとUIを利用できます。
ログの最後に以下のようなメッセージが出力されるので、この Root Token(hvs.0KXrA6oFiZnLBJpvoMnPc4vB
) を利用してログインします。
1WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
2and starts unsealed with a single unseal key. The root token is already
3authenticated to the CLI, so you can immediately begin using Vault.
4
5You may need to set the following environment variable:
6
7 $ export VAULT_ADDR='http://127.0.0.1:8200'
8
9The unseal key and root token are displayed below in case you want to
10seal/unseal the Vault or re-authenticate.
11
12Unseal Key: fxwAHiHVyi3vQdHGiFfTs4KuQUBkGtHZr0aELRfNTwg=
13Root Token: hvs.0KXrA6oFiZnLBJpvoMnPc4vB
14
15Development mode should NOT be used in production installations!
kv の secret engine を追加する
ログインすると以下のように作成済みの secret が見れます。dev 環境のためsecret
という key/value storage が作成されています。
今回は、新規で作成してみます。
-
テーブルの右上にある
Enable new secret
をクリックし作成ページに遷移します。 -
KV
を選択しNext
をクリックします。
- Path に
kv-test
を指定しEnable Engine
をクリックします。
(デフォルトではkv
が指定されてます)
- 作成された secret engine のページに遷移されます。
kv-test
に機密情報を登録する。
-
先ほどの
kv-test
のページのテーブルの右上にあるCreate secret
をクリックし作成ページに遷移します。 -
Path for this secret
にシークレットの名前を入力し、Secret data
に機密情報を Key/Value で入力します。
今回はシークレットの名前をmysql-prd
、機密情報をusername=prd-user
、password=prd-password
としてみました。
- 作成されたシークレットのページに遷移されます。
Ansible で取得する。
token の設定
Ansible で Vault を利用するために使用する Token を設定します。
playbook に直接記入できますが、メリットはないので ansible.cfg などに記述し git 管理しないようにします。
1$ cat <<EOF > ansible.cfg
2[hashi_vault_collection]
3token = "hvs.jkOyqGirKFHOLmpgIvneu52B"
4url = "http://127.0.0.1:8200"
5EOF
6$ echo "ansible.cfg" >> .gitignore
playbook の記述
kv(version 2) の secret engine からデータを取得する場合community.hashi_vault.vault_kv2_get
を利用します。
lookup の第 2 引数にシークレットの名前を指定します。また、engine の名前(kv-test
)をengine_mount_point
で指定します。
1cat <<EOF > playbook.yml
2- hosts: localhost
3 gather_facts: false
4 tasks:
5 - name: kv-testのデータを取得
6 ansible.builtin.set_fact:
7 response: "{{ lookup('community.hashi_vault.vault_kv2_get', 'mysql-prd', engine_mount_point='kv-test') }}"
8 - name: 結果を表示
9 ansible.builtin.debug:
10 msg:
11 - "Secret: {{ response.secret }}"
12 - "Data: {{ response.data }}"
13 - "Metadata: {{ response.metadata}}"
14 - "Full reponse: {{ response.raw }}"
15 - "Value of key 'username' in the secret: {{ response.secret.username }}"
16 - "Value of key 'password' in the secret: {{ response.secret.password }}"
17EOF
実行する。
先ほど UI で登録したデータを取得できていることが分かります。
1$ ansible-playbook playbook.yml
2[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
3
4PLAY [localhost] **********************************************************************************************************************
5
6TASK [kv-testのデータを取得] **********************************************************************************************************
7[DEPRECATION WARNING]: The default value for 'token_validate' will change from True to False. This feature will be removed from
8community.hashi_vault in version 4.0.0. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
9ok: [localhost]
10
11TASK [結果を表示] *********************************************************************************************************************
12ok: [localhost] => {
13 "msg": [
14 "Secret: {'password': 'prd-password', 'username': 'prd-user'}",
15 "Data: {'data': {'password': 'prd-password', 'username': 'prd-user'}, 'metadata': {'created_time': '2022-07-17T11:08:23.918173727Z', 'custom_metadata': None, 'deletion_time': '', 'destroyed': False, 'version': 1}}",
16 "Metadata: {'created_time': '2022-07-17T11:08:23.918173727Z', 'custom_metadata': None, 'deletion_time': '', 'destroyed': False, 'version': 1}",
17 "Full reponse: {'request_id': '8f43c6e5-9d3a-7dae-3121-2986e441cca9', 'lease_id': '', 'renewable': False, 'lease_duration': 0, 'data': {'data': {'password': 'prd-password', 'username': 'prd-user'}, 'metadata': {'created_time': '2022-07-17T11:08:23.918173727Z', 'custom_metadata': None, 'deletion_time': '', 'destroyed': False, 'version': 1}}, 'wrap_info': None, 'warnings': None, 'auth': None}",
18 "Value of key 'username' in the secret: prd-user",
19 "Value of key 'password' in the secret: prd-password"
20 ]
21}
22
23PLAY RECAP ****************************************************************************************************************************
24localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
さいごに
今回の検証で、Playbook と利用する機密情報を別々に管理することでより安全に機密情報を扱えるようになりました。
また、今回は Token に Root Token を利用しましたが、Ansible 実行用の Token や Policy を作成し利用することでさらに実用的になると思うので今後調べていきたいです。