Ansible Vault については多くの情報が公開されていますが、ここでは要件を以下の 3 点だけに絞って、簡単に実現する方法をまとめました。
- 機密情報の変数(パスワードなど)を暗号化する
- ターゲットに配置するファイル(秘密鍵など)を暗号化する
- Vault パスワードをスクリプトで管理する
参考: Ansible Vault — Ansible Documentation
- 確認環境:
- Ansible 2.10.7
- Ubuntu 20.04 / Debian 10 (buster)
準備: Vault パスワードを設定する
まず最も簡単な方法で Vault パスワードをファイルで設定します。
ここではパスワードを my_vaultp@ssw0rd
として、パスワードファイルを「~/.vault_pass」とします。
echo -n 'my_vaultp@ssw0rd' >~/.vault_pass
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
2 行目の ANSIBLE_VAULT_PASSWORD_FILE
は Ansible が参照する環境変数です。
ansible-vault
ansible-playbook
などのコマンドを実行すると、この環境変数が示すファイルに書かれているパスワードによって、変数やファイルが自動的に暗号化/復号化されます。
参考: Ansible Configuration Settings — Ansible Documentation
機密情報の変数(パスワードなど)を暗号化する
Vault 使用前
以下は all.yml という変数ファイルに、ユーザー名と平文のパスワードが定義されている例です。
group_vars/
└── all.yml
---
my_user: "user_1"
my_password: "myp@ssw0rd" # パスワード文字列 → 暗号化したい
Vault 使用後
この中の変数 my_password
の値を Vault で暗号化します。
まず変数ファイルを、元ファイルと同名のディレクトリ + 2 つのファイルに変更します。
group_vars/
└── all/ # 元の変数ファイルと同名のディレクトリ
├── vars # all.yml を移動してリネームする
└── vault # 新規作成
- 変数ファイル
all.yml
を新しいディレクトリ「all」の下に移動し、ファイル名をvars
に変更する - 同じ階層に
vault
というファイルを新規作成する(YAML)
vars を編集して、my_password
の値 myp@ssw0rd
を、「vault_
+ 元の変数名」という名前の新しい変数への参照に変更します。
my_user: "user_1"
- my_password: "myp@ssw0rd" # パスワード文字列 → 暗号化したい
+ my_password: "{{ vault_my_password }}" # 直値から「vault_ + 元の変数名」の参照に変更
新しい変数「vault_
+元の変数名」と値 myp@ssw0rd
は、新規作成したファイル vault 内で定義します。
---
vault_my_password: "myp@ssw0rd"
ansible-vault encrypt
コマンドを実行して vault を暗号化します。
ansible-vault encrypt group_vars/all/vault
vault が以下のような暗号ファイルに変換されます。
$ANSIBLE_VAULT;1.1;AES256
65656533363866316462313831663032353031626239633333323862323132616239306130303162
3531363266336538376239646430656134363132633339320a636531653933636336306339636666
(略)
同一ディレクトリ内のファイル vars と vault はペアで使用し、以下のルールを守って実装します。
- vault 内では
vault_
で始まる変数だけを定義し、ペアの vars からのみ参照する - vars 内で参照する
vault_
で始まる変数は、ペアの vault でのみ定義する
これによって vault が暗号化されたままでも、中で何が定義されているかが自明になります。
参考:
変数および Vault — ベストプラクティス — Ansible Documentation
Gitリポジトリ上でAWSアクセスキーを大公開しないためにAnsible Vaultをフル活用する | 株式会社ヌーラボ(Nulab inc.)
ターゲットに配置するファイル(秘密鍵など)を暗号化する
Vault 使用前
以下は、秘密鍵ファイル「secret_key」をターゲットホストに配置するロールの例です。
roles/
└── ssh_client/
├── files/
| └── secret_key # 暗号化していない秘密鍵ファイル
└── tasks/
└── main.yml
タスクファイルでは、ビルトインモジュールの「copy」を使って secret_key をターゲットに配置しています。
---
- name: Deploy secret key
ansible.builtin.copy:
dest: "/home/my_user/.ssh/secret_key"
mode: 0400
owner: "my_user"
src: "{{ role_path }}/files/secret_key"
秘密鍵ファイル secret_key は暗号化されていません。
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
hwqGhTJo8kiZehDGI6+5ZgZmNS5mpYI7576DAzPwZ7lF1YQhSYRwNWmPpFIT6mQb/RY6Ys
(略)
Vault 使用後
ansible-vault encrypt
コマンドで secret_key を暗号化します。
ansible-vault encrypt roles/ssh_client/files/secret_key
secret_key が以下のような暗号ファイルに変換されます。
$ANSIBLE_VAULT;1.1;AES256
65656533363866316462313831663032353031626239633333323862323132616239306130303162
3531363266336538376239646430656134363132633339320a636531653933636336306339636666
(略)
変更作業はこれだけです。
Ansible の copy モジュールは、ファイルが暗号化されていたら自動的に復号化してターゲットに配置してくれるので、タスクファイルを変更する必要はありません。
以下、「ファイルレベルの暗号化 — Ansible Vault — Ansible Documentation」から引用
Ansible Vault は、バイナリーファイルも含め、任意のファイルを暗号化できます。 vault で暗号化されたファイルが、 src 引数として、copy モジュール、template モジュール、 unarchive モジュール、script モジュール、または assemble モジュールとして指定されていると、ファイルは復号されたターゲットホストの宛先に配置されます (プレイの実行時に有効な vault パスワードが提供されている場合)。
Vault パスワードをスクリプトで管理する
平文ファイルの代わりに「Vault パスワードを標準出力に出力するスクリプト」を使用すれば、Vault パスワードの管理方法を自由に設計することができるようになります。
スクリプト化前
パスワードファイルを .gitignore に指定してソース管理の対象外とするため、開発メンバーには以下のファイルを別途配布する必要があります。
my_vaultp@ssw0rd
パスワードファイルのパスを指定する環境変数を環境ファイルに定義して、ソースと共に共有します。
開発環境が Docker なら、以下のような環境ファイルを docker-compose の env_file:
で設定します。
ANSIBLE_VAULT_PASSWORD_FILE="/workspace/.vault_pass"
開発環境が Docker でない場合は ~/.bashrc などで上記の環境変数を export
するか、または以下のように ansible.cfg で設定します。
vault_password_file = "/workspace/.vault_pass"
スクリプト化後
パスワードファイルの代わりに、「Vault パスワードを標準出力に出力するスクリプト」を使用します。
スクリプトのパスを同様に指定します。
ANSIBLE_VAULT_PASSWORD_FILE="/workspace/.vault_pass.sh"
環境変数の代わりに、以下のように ansible.cfg で指定する場合も同様です。
vault_password_file = "/workspace/.vault_pass.sh"
スクリプト自体はソース管理の対象にして共有し、スクリプトが出力する値を別途管理します。
以下は単純な例として、Vault パスワードを環境変数から取得して出力するスクリプトです。
# !/bin/bash
echo -n "${MY_VAULT_PASSWORD}"
もちろんこれでは環境変数 MY_VAULT_PASSWORD
を開発メンバーに別途配布する必要があるので、スクリプト化前から何も改善されていません。
しかしスクリプト化によって、今後の Vault パスワードの管理方法を自由に設計できるようになりました。
次回以降の課題
現実のプロジェクトで求められるセキュリティと運用の課題をクリアするために、以下の記事を追加しました。
次回: いまさら Ansible Vault (2): せめて開発・検証・本番環境の Vault パスワードを別々に - Qiita
次々回: いまさら Ansible Vault (3): Vault パスワードを環境ごとの AWS アカウントの SSM パラメータストアで管理する - Qiita