前々回の記事で Ansible ソース上の機密情報を Vault で暗号化して、前回の記事で開発・検証・本番環境の Vault パスワードを別々にしました。
しかしまだ Vault パスワードを管理するために、PC 内のファイルや環境変数を使用する必要があります。
そこで今回は以下の要件を実現します。
- Vault パスワードを暗号化してクラウドで管理する
- どのメンバーがどの環境の機密情報を取得できるかの許可や有効期限などを、クラウドの IAM で一元管理する
参考: Ansible Vault — Ansible Documentation
- 確認環境:
- Ansible 2.10.7
- Ubuntu 20.04 / Debian 10 (buster)
AWS SSM パラメータストア
クラウドで Vault パスワードを暗号化して管理するためのストアとして、AWS の SSM パラメータストア(Systems Manager Parameter Store)を使用します。
AWS のストアには、より機密情報の管理に特化した Secrets Manager もあるのですが、今回は無料で利用できて汎用的な SSM パラメータストアを選択しました。
参考:
AWSのParameter StoreとSecrets Manager、結局どちらを使えばいいのか?比較 - Qiita
AWS Systems Manager Parameter Store - AWS Systems Manager
AWS アカウント
開発・検証・本番環境ごとに AWS アカウントを別々にして、計 3 つの AWS アカウントを使用します。
1 つの AWS アカウントで全環境を管理することもできますが、本記事の文脈では AWS アカウントを別々にすることで、個々のメンバーに対して環境ごとのアクセス権を与えるかどうかを簡単に管理できることが大きなメリットになります。
参考:
AWS導入前に知っておきたかった「AWSアカウント設計」 - IST techブログ
AWS アカウント作成の流れ | AWS
AWS IAM ユーザーと認証情報ファイル
各メンバーのために、アクセスを許可する環境の AWS アカウントごとに IAM ユーザーを作成して、アクセスキーが書かれた認証情報ファイル(~/.aws/credentials
)を配布します。
参考:
IAM ユーザー - AWS Identity and Access Management
名前付きプロファイル - AWS Command Line Interface
各環境用のプロファイル名は、環境名および Vault ID と同じ「dev」「stg」「prd」とします。
以下は全環境の AWS アカウントにアクセスするための認証情報ファイルの例です。
[dev]
aws_access_key_id = AXXXXXXXXXXXXXXXXXXX
aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
region = ap-northeast-1
output = yaml
[stg]
aws_access_key_id = AYYYYYYYYYYYYYYYYYYY
aws_secret_access_key = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
region = ap-northeast-1
output = yaml
[prd]
aws_access_key_id = AZZZZZZZZZZZZZZZZZZZ
aws_secret_access_key = zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
region = ap-northeast-1
output = yaml
AWS CLI のインストール
Vault パスワード取得用スクリプトが AWS SSM パラメータストアにアクセスできるように、各メンバーの PC やコンテナに AWS CLI をインストールします。
curl -L "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \
-o "awscliv2.zip" \
&& unzip -oq "awscliv2.zip" \
&& sudo aws/install
参考: AWS CLI バージョン 2 のインストール、更新、アンインストール - AWS Command Line Interface
Vault パスワードを各 AWS アカウントのパラメータストアに保存する
パラメータストアに保存するパラメータ名は全環境で共通の MY_VAULT_PASSWORD
とし、環境ごとの Vault パスワードは各ディレクトリ内のファイル「MY_VAULT_PASSWORD.secret」に書かれているとします。
.
├── dev
│ └── MY_VAULT_PASSWORD.secret # dev 環境用の Vault パスワードが書かれている
├── stg
│ └── MY_VAULT_PASSWORD.secret # stg 環境用の Vault パスワードが書かれている
└── prd
└── MY_VAULT_PASSWORD.secret # prd 環境用の Vault パスワードが書かれている
*.secret ファイルをコミットしてしまわないように注意しましょう。
以下は例では、各環境の Vault パスワードを *.secret ファイルから読み取って、それぞれの AWS アカウントのパラメータストアに保存します。
for profile in $(ls .); do
# 環境ごとのディレクトリ(dev|stg|prd)内の *.secret ファイルを対象とする
for file in $(find ${profile} -name "*.secret" -print); do
# パラメータ名はファイル名と同じ(拡張子除く)
name="$(basename "${file}" .secret)"
# AWS プロファイルは、環境名およびディレクトリ名と同じ(dev|stg|prd)
aws ssm put-parameter \
--type SecureString \
--name "${name}" \
--value "$(cat "${file}")" \
--profile "${profile}"
done
done
参考: put-parameter — AWS CLI 2.2.45 Command Reference
Vault パスワード取得スクリプトの改良
前回の記事のとおり環境変数 ANSIBLE_VAULT_IDENTITY_LIST に,
{ID 1}@{スクリプト 1}, {ID 2}@{スクリプト 2}, ...
のように Vault ID と スクリプトのペアをいくつでも指定できます。
ANSIBLE_VAULT_IDENTITY_LIST="dev@/workspace/vault_pass_dev.sh, stg@/workspace/vault_pass_stg.sh, prd@/workspace/vault_pass_prd.sh"
以下のスクリプトは、上記の dev@/workspace/vault_pass_dev.sh
で「dev」に紐づけられているスクリプト「vault_pass_dev.sh」を改良する例です。
# !/bin/bash
AWS_PROFILE="dev" # dev 環境用
aws ssm get-parameter \
--name "MY_VAULT_PASSWORD" \
--with-decryption \
--output json \
--profile ${AWS_PROFILE} \
| jq -r .Parameter.Value \
| tr -d '\n'
パラメータ名 MY_VAULT_PASSWORD
として保存された暗号文字列を復号化してパラメータストアから取得し、値だけを抽出して標準出力に出力します。
参考: get-parameter — AWS CLI 2.2.45 Command Reference
「stg」「prd」環境用のスクリプトも同様に改良します。
以上で、ansible-playbook
や ansible-vault
などのコマンドを実行する時に --profile
オプションで指定した環境用の Vault パスワードを、それぞれの AWS アカウント内の SSM パラメータストアから自動的に復号化して取得できるようになりました。