はじめに
ECSタスクのコンテナからRDSなどの外部ストレージにアクセスする場合、AWS Secrets Manager
のような秘匿情報を管理するマネージドサービスを使用して、セキュリティ面に配慮する必要があります。
チームの方針によってはプロダクション環境以外ではAWS Secrets Manager
で管理することの優先度を下げる場合があるかと思いますが、基本的にはAWS Secrets Manager
経由で秘匿情報を参照するのが望ましいと思います。
ECSからAWS Secrets Manager
にアクセスする
ECSからAWS Secrets Manager
にアクセスする際に少し躓くポイントがあったので、ここで整理をしてみます。
VCPエンドポイントと紐付ける
あらかじめVPCエンドポイントを作成しておき、デプロイするECSのサービスを作成したVPC内に所属させる必要があります。
IAMポリシーを適切に付与する
秘匿情報が保管されているAWS Secrets Manager
と、暗号化された秘匿情報を複合化するためのAWS Key Management Service
にアクセスするための権限をECSタスク実行ロールに付与する必要があります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"kms:Decrypt"
],
"Resource": [
"arn:aws:secretsmanager:<region>:<aws_account_id>:secret:<secret_name>",
"arn:aws:kms:<region>:<aws_account_id>:key/<key_id>"
]
}
]
}
発生していたエラー
ECSのタスク実行ロールに上記の権限を付与できていないと、タスク実行時に以下のようなエラーが出てしまいECSクラスターにデプロイすることができません。
ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve secret from asm: service call has been retried 5 time(s): failed to fetch secret
arn:aws:secretsmanager:ap-northeast-1:xxxxxxxx:secret:prod/project/xxxxxxxxxx from secrets manager: RequestCanceled: request context canceled caused by: context deadline exceeded
(補足)AWS Key Management Service
データの暗号化、複合化に関するマネージドサービスです。
タスク定義について
{
"containerDefinitions": [
{
"name": "server",
"image": "xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/grpc-server",
"cpu": 0,
"memoryReservation": 300,
"portMappings": [
{
"containerPort": 50051,
"hostPort": 50051,
"protocol": "tcp"
}
],
"essential": true,
"secrets": [
{
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxx:secret:prod/project/xxxxxxxxx:host::",
"name": "DB_HOST"
},
{
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxx:secret:prod/project/xxxxxxxxx:dbClusterIdentifier::",
"name": "DB_NAME"
},
{
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxx:secret:prod/project/xxxxxxxxx:password::",
"name": "DB_PASS"
},
{
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxx:secret:prod/project/xxxxxxxxx:port::",
"name": "DB_PORT"
},
{
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxx:secret:prod/project/xxxxxxxxx:username::",
"name": "DB_USER"
}
],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/grpc-server-task",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"family": "grpc-server-task",
"taskRoleArn": "arn:aws:iam::xxxxxxxxxx:role/ecsTaskExecutionRole",
"executionRoleArn": "arn:aws:iam::xxxxxxxxxx:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"volumes": [],
"placementConstraints": [],
"runtimePlatform": {
"operatingSystemFamily": "LINUX"
},
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"tags": []
}
containerDefinitions
のsecrets
フィールドを使用する
"secrets": [
{
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxx:secret:prod/project/xxxxxxxx:host::",
"name": "DB_HOST"
},
AWS Secrets Manager
に登録した秘匿情報を参照するためには、上記のようにsecretsフィールドに環境変数を定義する必要があります。
AWSコンソールからAWS Secrets Manager
→シークレット
とアクセスし、「シークレットのarn」を取得しましょう。
シークレットの値を参照するための記法
シークレットに定義された各変数を参照するためには以下のように記載する必要があります。
シークレットのarn:キー名::
上記の記法でtask定義を行わないとシークレットの値を正しく参照できないので注意しましょう。
**RoleArnについて
"taskRoleArn": "arn:aws:iam::xxxxxxxxxx:role/ecsTaskExecutionRole",
"executionRoleArn": "arn:aws:iam::xxxxxxxxxx:role/ecsTaskExecutionRole",
AWS Secrets Manager
およびAWS Key Management Service
へのアクセス権限を付与したtaskRoleを使用するようにtask定義ファイルの中できちんと明示しましょう。
終わりに
今回の記事に書かれたポイントを押さえると、秘匿情報をAWS Secrets Manager
から取得した上でコンテナを起動することができると思います。
ECSへのtask定義ファイルに秘匿情報をベタ書きして運用をするようなことがないように注意しましょう。
参考記事