ゴール
AWS CodePipeline で taskdef.json をアーティファクトとして CodeDeploy に渡す場合がある。
この taskdef.json を元にしてECSコンテナ用のタスクが作成されるわけだが、この時 AWS Secrets Manager で設定している機密データが参照されるよう、うまく下図のようにタスク定義内に環境変数として設定したい。
そうすると、APIのキーやDBのID/PWなど、そういった秘匿したい情報をコンテナ側のプログラムに引き渡すのに便利だ。
その設定をするコードスニペットをメモする。
(なお、本稿ではCodePipelineの設定などは割愛する。)
Secrets Manager での設定について
任意のシークレットを作成して、キー(名前)と値の組み合わせを好きな個数保存しておく。
なお、このシークレットのARNは、後述されるが、後で使う。
taskdef.json の準備
適宜構成情報を記述した taskdef.json を builspef.yml と同じディレクトリに用意しておく。1
builspef.yml 内での設定方法
やりたいことは taskdef.json 内の containerDefinitions の定義内に secrets という項目をまず生やす。そこへ name と valueFrom のペア値を配列で、必要な分だけ挿入する。そうすることでコンテナ作成時に Secrets Manager から値が参照されて値がコンテナ内の環境変数として設定されるようになる。2
なお、name がコンテナ内での環境変数名、 valueFromが対象シークレットのキーのARNである。
この containerDefinitions.secrets への値の注入を buildspec.yml で定義する。
jq を活用する。
post_build フェーズあたりで設定するのが妥当かな。コードは次のとおり。
このコードによって、例えばシークレット内でキー名を PIYOPIYO として値を定義すると、コンテナの環境変数 PIYOPIYO が設定される。
post_build:
commands:
- (...中略...)
# Injecting secrets value from Secrets Manager
- SECRETS='[]'
- |
for KEY in $(aws secretsmanager get-secret-value --region ap-northeast-1 --secret-id $BUILD_SECRETMANGER_ARN | jq -r ".SecretString" | jq -r ". | keys | @sh")
do
KEY=$(echo $KEY | tr -d "'")
VALUEFROM="${BUILD_SECRETMANGER_ARN}:${KEY}::"
NEW_ITEM=$(printf '{"name":"%s", "valueFrom":"%s"}' $KEY $VALUEFROM)
SECRETS=$(echo $SECRETS | jq ".+[$NEW_ITEM]")
done
- cat taskdef.json | jq ".containerDefinitions[0].secrets=$SECRETS" > ./taksdef.json.tmp
- mv taksdef.json.tmp taksdef.json
(注釈)
- ここで用いられている
BUILD_SECRETMANGER_ARNは、対象のシークレットのARNを保持するビルド時の環境変数。CodeBuildの環境変数としてセットしておくと良いだろう。 - また、CodeBuildの実行ロールに
AmazonSSMReadOnlyAccessを設定しておくのを忘れずに。
その他
今回のやり方と同様の方法で、パラメータストアで設定した値を用いることもできる。3
パラメータストアを用いる場合も Secrets Manager と同様のことをすれば良いが、この場合は valueFrom の値はARNではなくパラメータ自体の名前でも大丈夫だ。4
- NEW_ITEM=$(printf '{"name":"%s", "valueFrom":"%s"}' "${注入したい環境変数名}" "${パラメータの名前}")
- SECRETS=$(echo $SECRETS | jq ".+[$NEW_ITEM]")
(以上)
