はじめに
AWSのコンテナオーケストレーションサービスであるECS Fargateは、多くの企業で本番環境のインフラとして採用されています。しかし、アプリケーションが使用するデータベースの接続情報や外部APIの認証キーといった「機密情報(シークレット)」を、コンテナイメージ内に直接埋め込んだり、タスク定義の環境変数にプレーンテキストで記述したりすることは、セキュリティ上の重大なリスクとなります。
本記事では、AWS Systems Manager(SSM)のパラメータストアを使用し、ECS Fargateタスクへ安全に機密情報を環境変数として注入するための具体的な設定手順とベストプラクティスを、初心者にも分かりやすく解説します。
前提知識/必要な理由
ECS Fargateで機密情報を扱う際、機密情報を安全に保管するストレージとして「SSMパラメータストア」または「AWS Secrets Manager」を利用するのが標準的な設計です。
今回は、低コストかつシンプルに導入できるSSMパラメータストア(安全な暗号化文字列を保存できるSecureString型)を使用します。この構成を採用する理由は以下の通りです。
- ソースコードと機密情報の分離: コードリポジトリやコンテナイメージにパスワードを含める必要がなくなります。
- タスク定義の秘匿化: ECSタスク定義ファイル(JSON)内にも値が直接書き込まれないため、AWSコンソールやログからの漏洩を防げます。
- コンテナ起動時の自動注入: AWSのコントロールプレーンが、コンテナの起動時にSSMから値を取得し、環境変数としてコンテナプロセスに安全に注入します。アプリケーション側に特別なライブラリ(AWS SDKなど)を実装する必要はありません。
具体的な設定手順・設計方法
それでは、SSMパラメータストアに保存した機密情報を、ECS Fargateの環境変数としてコンテナに渡す手順を解説します。
ステップ1: SSMパラメータストアに機密情報を登録する
まずは、AWS CLIまたはAWS管理コンソールを使用して、機密情報をSecureString型(暗号化文字列)で登録します。
以下は、AWS CLIを使用してデータベースのパスワードを登録するコマンドの例です。
aws ssm put-parameter \
--name "/production/app/DB_PASSWORD" \
--value "SuperSecretPassword123!" \
--type "SecureString" \
--key-id "alias/aws/ssm"
※標準のAWSマネージドキー(alias/aws/ssm)を使用していますが、実務ではセキュリティ要件に応じてカスタマイズしたカスタマー管理型のKMSキー(CMK)を使用することを推奨します。
ステップ2: ECSタスク実行ロールにIAM権限を付与する
ECSエージェントがコンテナ起動時にSSMパラメータストアから値を取得し、KMSで復号するためには、「ECSタスク実行ロール(Task Execution Role)」に適切な権限を付与する必要があります。(※「タスクロール」ではない点に注意してください)
既存のタスク実行ロールに、以下のIAMインラインポリシーをアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameters",
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:ssm:ap-northeast-1:123456789012:parameter/production/app/*"
]
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": [
"arn:aws:kms:ap-northeast-1:123456789012:key/your-custom-kms-key-id"
]
}
]
}
※ 123456789012 はご自身のAWSアカウントIDに、KMSのARNは使用している鍵のARNに置き換えてください。デフォルトの alias/aws/ssm を使用している場合、KMSの復号権限は自動的に解決されるため、上記 kms:Decrypt の明示的な追加は不要な場合があります。
ステップ3: ECSタスク定義で環境変数とSSMを紐付ける
次に、ECSタスク定義のコンテナ定義(containerDefinitions)内で、SSMパラメータストアのARNを参照するように設定します。environment ではなく secrets セクションを使用するのがポイントです。
タスク定義のJSONファイルに、以下のように記述します。
{
"containerDefinitions": [
{
"name": "web-app",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest",
"essential": true,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80
}
],
"secrets": [
{
"name": "DATABASE_PASSWORD",
"valueFrom": "arn:aws:ssm:ap-northeast-1:123456789012:parameter/production/app/DB_PASSWORD"
}
]
}
],
"family": "my-app-task",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
この設定により、コンテナ内のアプリケーションからは、通常の環境変数 DATABASE_PASSWORD として暗号化解除された生のパスワードにアクセスできるようになります。アプリケーション側での特別なデコード処理は一切不要です。
実務での注意点
- タスク実行ロールとタスクロールの混同: 機密情報の取得に必要な権限は「タスク実行ロール(executionRoleArn)」に付与してください。アプリケーション自体がAWSリソースにアクセスするための「タスクロール(taskRoleArn)」に付与しても、コンテナ起動時のパラメータ取得は失敗します。
- ネットワーク経路の確保: Fargateタスクがプライベートサブネットで起動する場合、SSMサービスエンドポイントと通信できる必要があります。NATゲートウェイを経由するか、VPC内にSSM用のインターフェース型VPCエンドポイント(ssm, ssmmessages, ec2messages)を配置してください。
- パラメータのバージョン管理: SSMパラメータを更新しても、実行中のFargateコンテナ内の環境変数は自動的に更新されません。新しい値を反映させるには、ECSサービスの「新しいデプロイの強制」を実行してタスクを再起動する必要があります。
まとめ
ECS Fargateにおける機密情報の管理は、SSMパラメータストアとタスク実行ロールを組み合わせることで、アプリケーションコードに手を加えることなくセキュアに実装できます。この方法はAWSのベストプラクティスに準拠しており、インフラの監査対応やセキュリティ向上において必須の設計パターンです。ぜひ本手順を参考に、安全なコンテナ環境を構築してください。