SUPER-G.EEK.JP

twitter: @hum_op_dev
github: ophum

AnsibleでHashiCorp Vaultに登録した機密情報を使用する

目次

HashiCorp Vault(以下 vault)を利用してパスワードなどの機密情報を保存し、それを Ansible で利用してみました。

検証環境

$ 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 向けのパッケージマネージャでインストールすることができます。
今回はバイナリをダウンロードしました。

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 が作成されています。
今回は、新規で作成してみます。

  1. テーブルの右上にあるEnable new secretをクリックし作成ページに遷移します。

  2. KVを選択しNextをクリックします。

  1. Path にkv-testを指定しEnable Engineをクリックします。
    (デフォルトではkvが指定されてます)

  1. 作成された secret engine のページに遷移されます。

kv-testに機密情報を登録する。

  1. 先ほどのkv-testのページのテーブルの右上にあるCreate secretをクリックし作成ページに遷移します。

  2. Path for this secretにシークレットの名前を入力し、Secret dataに機密情報を Key/Value で入力します。
    今回はシークレットの名前をmysql-prd、機密情報をusername=prd-userpassword=prd-passwordとしてみました。

  1. 作成されたシークレットのページに遷移されます。

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 を作成し利用することでさらに実用的になると思うので今後調べていきたいです。

参考文献