ECSを運用するときにDBパスワードなどの機密データ(秘密・秘匿情報、シークレット)を、どうやってコンテナ内に渡すか悩みどころだと思います。
例えばdotenvを利用した場合、機密データが記述された.envをおいそれとGitHubにコミットするのはリスクがあるため、コンテナへ.envをデプロイすることも難しくなると思います。
そこで機密データを管理するためのAWSサービスである Secrets Manager もしくは Systems Managerのパラメータストア を利用します。(使い分けはこちらのQiitaが参考になります)
今回はこの2つのサービスからECSコンテナの環境変数に機密データを埋め込んでみます。
前提
ECS Execの有効化
手順の最後にコンテナに入って環境変数の確認を行うため、以下の記事を参考にしながらECS Execを有効化してください。(機密データの埋め込み自体に必要な設定というわけではないです)
ECS環境変数への機密データの設定手順
Secrets Managerでシークレットの作成
AWSマネジメントコンソールの画面上部検索窓 [ Secrets Manager ] で検索 → 当該サービスをクリック → 画面右上の[ 新しいシークレットを保存する ] をクリックします。
次の画面から以下のとおり設定します。明記してない項目はデフォルトのままでOKです。
項目名 | 値 |
---|---|
シークレットのタイプ | その他のシークレットのタイプ |
キー | ecs |
値 | from-secretsmanager |
シークレットの名前 | demo |
Systems Managerでパラメータの作成
AWSマネジメントコンソールの画面上部検索窓 [ Systems Manager ] で検索 → 当該サービスをクリック → 画面左ペイン アプリケーション管理の [ パラメータストア ] → 画面右上の [ パラメータの作成 ] をクリックします。
次の画面から以下のとおり設定します。明記してない項目はデフォルトのままでOKです。
項目名 | 値 |
---|---|
名前 | /secrets/demo/ecs |
タイプ | 安全な文字列 |
値 | from-parameterstore |
ECSのタスク実行ロールにIAMポリシーの追加
ECSのタスク実行ロールへ以下のIAMポリシーを付与します。
Secrets Manager と Systems Managerのパラメータストアで作成したリソースへの読み込みアクセスを許可しています。
{
"Statement": [
{
"Action": [
"ssm:GetParameters",
"secretsmanager:GetSecretValue"
],
"Effect": "Allow",
"Resource": [
"arn:aws:ssm:ap-northeast-1:AWSアカウントID:parameter/secrets/demo/ecs",
"arn:aws:secretsmanager:ap-northeast-1:AWSアカウントID:secret:demo-設定されたランダムな文字列"
]
}
],
"Version": "2012-10-17"
}
ECSのタスク定義に機密データの設定
AWSマネジメントコンソールの画面上部検索窓 [ ECS ] で検索 → 画面左ペイン [ タスク定義 ] → 当該タスク定義 → 最新リビジョン → [ 新しいリビジョンの作成 ] をクリックします。
環境変数を設定するコンテナをクリックし [ 環境 ] の [ 環境変数 ] を以下のとおり設定します。(新規にタスク定義を作成する場合も同様です)
キー | 値 |
---|---|
FROM_PARAMETERSTORE_ARN | arn:aws:ssm:ap-northeast-1:AWSアカウントID:parameter/secrets/demo/ecs |
FROM_PARAMETERSTORE_NAME | /secrets/demo/ecs |
FROM_SECRETSMANAGER_ARN | arn:aws:secretsmanager:ap-northeast-1:AWSアカウントID:secret:demo-設定されたランダムな文字列 |
FROM_SECRETSMANAGER_ARN_KEY | secretsmanager:ap-northeast-1:AWSアカウントID:secret:demo-設定されたランダムな文字列:ecs:: |
SSMパラメータストアの指定はARNか、ECSと同じリージョンであれば名前のみの設定でもOKです。
シークレットマネージャーはARNを指定します。ただARNのみであるとJSON形式で値が取得されるため、ARNの最後に :キー:: とJSONの当該キーを指定することで、その値のみを取得できるようになります。
注意点としてこちらに記載のとおり、キーの後ろにはversion-stageとversion-idを省略していることになるため最後にコロン2つ(::)をつけることを忘れないでください。
忘れるとECS起動時に以下のエラーとなります。
ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve secret from asm: service call has been retried 1 time(s): secrets manager: failed to retrieve secret from arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:demo-xxx:ecs: unexpected ARN format with parameters when trying to retrieve ASM secret
ECSコンテナ内の環境変数の確認
環境変数を設定したタスク定義で更新されたコンテナに対して、ECS Execを使ってenvコマンドを実行してみます。
以下のように環境変数に機密データが設定されていることが確認できます。
$ aws ecs list-tasks --cluster demo
{
"taskArns": [
"arn:aws:ecs:ap-northeast-1:123456789012:task/demo/1b960xxxxx"
]
}
$
$ aws ecs execute-command --cluster demo --task 1b960xxxxx --container demo --interactive --command env |grep FROM |sort
FROM_PARAMETERSTORE_ARN=from-parameterstore
FROM_PARAMETERSTORE_NAME=from-parameterstore
FROM_SECRETSMANAGER_ARN={"ecs":"from-secretsmanager"}
FROM_SECRETSMANAGER_ARN_KEY=from-secretsmanager
$
今回は以上です〜ノシ
参考
(`・ω・´)ノ アリガトウゴザイマス!!
Amazon ECS 機密データの指定
AWSのParameter StoreとSecrets Manager、結局どちらを使えばいいのか?比較
ECSでコンテナ環境変数をSecretManagerから取得する際にResourceInitializationErrorが発生したときの対処方法