こんにちは。X(クロス)イノベーション本部 ソフトウェアデザインセンター の山下です。 今回は、Ansible Vaultを利用して、Ansibleを使う場合に機密情報を安全に扱う方法について紹介します。
ansibleと機密情報の管理についての課題
Ansibleを使ってデプロイなどを自動化していると、Amazon Web Services(AWS) の機密情報やパスワード、SSHに利用する秘密鍵といった機密情報を扱う場面があります。また、Ansibleを利用している場合はplaybookをGitHubなどで管理することが多いと思います。こういったGitHubなどのリポジトリに機密情報を直接置いてしまうと情報漏洩といった事故につながる場合があります。
機密情報を別システム ( dashlaneやAWSのsecret managerなど ) で管理するといった方法もあるかと思います。しかしこの方法では機密情報だけをバージョン管理の仕組みから別で管理することとなってしまい、管理コストが高くなってしまいます。また、CI/CDといった自動化を行う場合にもansible以外のツール、機密情報へのアクセス方法を考えなければならなくなってしまいます。
理想的には以下のような状態になっていてほしいです。
- 機密情報は安全に扱いたい
- 新規のツールの導入は避けたい
- playbookと機密情報の両方を1つのリポジトリ上で安全にバージョン管理できる
今回はこの問題を解決するAnsible Vaultというツールについて紹介します。
Ansible Vaultとは
このような機密情報を扱うために、AnsibleにはAnsible Vaultと呼ばれる暗号化の機能が付属しています。暗号化した情報であればリポジトリ上に置くリスクを大幅に減らすことができます。本記事ではこのAnsible Vaultを使って、sshの秘密鍵、AWSの認証情報といった機密情報を暗号化してCI/CDから利用する方法について記載します。
なお、Ansible Vaultの公式のドキュメントは以下となります。より詳細な説明は以下のドキュメントを参照してください。 https://docs.ansible.com/ansible/latest/user_guide/vault.html
この記事で紹介している利用方法は、
- 10人に満たない小規模なチーム
- 機密情報はメンバ内で共有して問題がない
上記のような想定となっています。
このため、Ansible Vaultで暗号化に利用するパスワードはvaultd-id
を利用して分割したりせず単一で共通のものを想定しています。
Ansible Vaultを使った暗号化、復号化
Ansible Vaultは、ansible-vault
コマンドを通じて利用します。サブコマンドとしてcreate
、encrypt
、 decrypt
、 rekey
、 edit
、view
というサブコマンドがあります。ここでは、既存のファイルの暗号化、復号を行うencrypt
、decrypt
の動作について述べます。
まずは、encrypt
を使ってファイルを暗号化してみましょう。以下のような中身のファイルを、test.txt
という名前で作成します。
hello,world!
そのファイルを、ansible-vault encrypt
で暗号化します。
途中でパスワードを聞かれるので、適宜入力して忘れない様にしてください。
$ansible-vault encrypt test.txt New Vault password: Confirm New Vault password: Encryption successful
暗号化に成功したようです。暗号化された中身を確認してみます。
$ cat test.txt $ANSIBLE_VAULT;1.1;AES256 34646636663564393432303436353932613263346534373439353133303137333064343363326266 6565386564393437316139353031333063316663363466300a376534313035373630356663376661 35663263663265383861346162306630353636316534626165313638616433373566373632306339 6438646236316431380a643737343561376133313334616162303737616561386262633338313761 6436
ちゃんと暗号化できたようです。
今度は復号できるか確認してみましょう。復号に使うコマンドはansible-vault decrypt
です。
途中で先ほど入力したパスワードを求められます。打ち間違いに注意してパスワードを入力しましょう。
ansible-vault decrypt test.txt Vault password: Decryption successful
無事復号できたようです。 それでは、中身も正しいかを確認してみましょう。
$ cat test.txt hello,world!
ちゃんとファイルの中身も復号できていることが分かりました。
このansible-vault
の機能を使って機密情報を扱うplaybookを作ってみましょう。
SSH接続情報の保護
ansibleではSSHの接続に秘密鍵を利用することが多いですが、この秘密鍵をリポジトリに暗号化せずに登録してしまうと、その情報を入手した人は誰でも接続できてしまいます。まずはこの情報の暗号化を実施してみましょう。
まず、以下のように接続に利用する秘密鍵(private_key
)を暗号化しておきます。
ansible-vault private_key
次に、実行するplaybookの先頭にこの暗号化された秘密鍵を復号するタスクを追加します。
内容としてはcopy
モジュールを実行するだけのものになっています。ansibleのcopy
モジュールは、ansible-vault
で暗号化されたファイルを扱う際に復号してくれる機能があります。その機能を利用して、秘密鍵を復号しています。
- hosts: localhost gather_facts: false vars: src_key: ./private_key dest_key: ./decrypted_private_key tasks: - copy: src: "{{ src_key }}" dest: "{{ dest_key }}" mode: 0600
そして ansible-playbook
で利用する inventory.yml
を以下のように記述します。
XXXで示している部分は各自の環境に合わせて書き換えてください。
ここで、ansible_ssh_private_key_file
には上記の手順で復号された秘密鍵が指定されるように設定します。
all: children: XXXX: hosts: XXXX: ansible_ssh_private_key_file: ./decrypted_private_key ansible_ssh_user: XXXX ansible_host: XXX.XXX.XXX.XXX ungrouped: {}
これで、秘密鍵を暗号化して管理することが可能になりました。
機密情報を利用するPlaybookの実行方法
ansible-playbook
を実行する際にvaultで利用したパスワードが必要になりました。
以下のように引数でパスワードファイルを渡すか、毎回入力する方法があります。
自動化などを考えるとパスワードファイルを作成する方法が手軽です。
# 端末で毎回パスワードを入力する方法 ansible-playbook site.yml -ask-vault-pass # パスワードファイルを引数で与える方法 ansible-playbook site.yml –vault-password-file ~/.vault_pass.txt
例えば、環境変数$VAULT_PASS
にパスワードが格納されているような場合では、以下のようなスクリプトを実行する方法があります。
echo "$VAULT_PASS" > .vault_pass.txt ansible-playbook -i inventory.yml site.yml –vault-password-file ~/.vault_pass.txt rm .vault_pass.txt
Playbook上で利用する機密情報の保護
ここまででSSHに利用する秘密鍵の暗号化は実現できました。次にplaybookの中で利用したい機密情報についても暗号化していきましょう。
先ほどの秘密鍵の例では、copy
モジュールは自動的にansible-vault
の復号を実施してくれると説明しました。この機能がansibleの変数のファイルに対しても自動的に復号を行ってくれます。
従ってAnsibleが利用する group_vars/all.yml
といった変数ファイルをansible-vault
コマンドで事前に暗号化しておくことで、機密情報を暗号化したままで利用することが出来ます。以下のように事前に変数のファイルを暗号化しておくだけで安全に管理することが可能となります。
group_vars/all.yml
には以下のように、sudoのパスワードやAWSの接続情報が含まれています。
--- ansible_sudo_pass: "XXXXXXXXXX" aws_access_key_id: "XXXXXXXXXXXXXXXXXXX" aws_secret_access_key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
これを、ansible-vault
で暗号化します。
ansible-vault encrypt group_vars/all.yml
この状態で、ansible-playbook
の実行時にgroup_vars/all
の変数を利用する際に自動的に復号処理が行われます。
実行方法は前項で述べた方法と変わらず実行できます。
GitHub Actions で実行する方法
それでは、最後にGitHub Actionsで実行する場合の方法について紹介します。 vaultのパスワードをGitHubのsecretとして与えるような設定を行って実行します。
jobs: deploy: steps: - name: Exec ansible-playbook env: VAULT_PASS: ${{secrets.VAULT_PASS}} run: | echo $VAULT_PASS > ./vault_pass.txt ansible-playbook -i inventory.yml site.yml --vault-password-file ./vault_pass.txt"
簡単ですね!
まとめ
この記事では、Ansible Vaultを使った機密情報の扱い方の簡単な紹介を行いました。またそれらを組みわせてGitHub Actionsから実行する方法も紹介しました。これで、安全にリポジトリ上の機密情報を置きながら、CI/CDも手軽に実行できる環境が構築できます。仮想マシンなどにサービスをAnsibleを使ってデプロイする場面では是非有効活用していきたいですね。
私たちは同じチームで働いてくれる仲間を探しています。今回のエントリで紹介したような仕事に興味のある方、ご応募お待ちしています。
執筆:@yamashita.tsuyoshi、レビュー:@sato.taichi (Shodoで執筆されました)