はじめに
Amazon ECS(Fargate)でアプリケーションを構築する際、データベースの接続パスワードやAPIキーなどの「機密情報(シークレット)」をどのように管理すべきか悩む方は多いのではないでしょうか。コンテナイメージやタスク定義に機密情報を直接ハードコーディングすることは、セキュリティ上絶対に避けるべきです。
本記事では、AWSのベストプラクティスである「AWS Secrets Manager」と「Amazon ECS」を連携させ、安全に機密情報を環境変数としてコンテナに注入する具体的な設定手順を、初心者にもわかりやすくステップバイステップで解説します。
前提知識/必要な理由
なぜAWS Secrets Managerを使用するのか?
AWS Secrets Managerを使用することで、インフラ運用において以下のメリットが得られます。
- 機密情報の強力な暗号化保存(AWS KMSによる自動暗号化)
- ソースコードや設定ファイル、GitHubなどのGit管理下からの機密情報の完全な排除
- 安全なシークレットのローテーション(自動更新)の実現
ECSとの連携の仕組み
ECSでは、「タスク実行ロール(Task Execution Role)」に対してSecrets Managerへの読み取り権限を付与することで、コンテナ起動時にECSエージェントが自動的にシークレットを取得し、コンテナの環境変数に安全に注入(インジェクション)してくれます。
これにより、コンテナ内部のアプリケーションにAWS SDKを導入して個別にシークレット取得処理を実装する必要がなくなり、プログラムのコードを非常にシンプルに保つことができます。
具体的な設定手順・設計方法
ここからは、AWSコンソールや設定ファイルを用いた具体的な手順を解説します。今回は、データベースのパスワード情報をSecrets Managerに保存し、それをECSタスク定義経由で取得する構成を例にします。
ステップ1:Secrets Managerでのシークレット作成
まずは、保護したい機密情報をSecrets Managerに登録します。
- AWSコンソールで「Secrets Manager」を開き、「新しいシークレットを保存する」をクリックします。
- シークレットのタイプで「その他のシークレットのタイプ」を選択し、キー/値のペアとして以下を入力します。
- キー:
DB_PASSWORD - 値:
SuperSecretPassword123!
- キー:
- シークレット名(例:
myapp/production/db)を設定し、保存します。 - 作成完了後、詳細画面に表示されるシークレットの「ARN(Amazon Resource Name)」をコピーして控えておきます。
ステップ2:タスク実行ロールのIAMポリシー設定
ECSエージェントがシークレットを取得できるように、タスク実行ロールへ権限を付与します。既存のタスク実行ロール(通常は ecsTaskExecutionRole)に、以下のカスタムIAMポリシーを作成してアタッチしてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:myapp/production/db-xxxxxx"
]
}
]
}
※上記ポリシー内の「Resource」には、ステップ1で控えた実際のシークレットARNを記述してください。
ステップ3:ECSタスク定義の設定
次に、ECSのタスク定義を編集し、コンテナの環境変数としてシークレットを指定します。タスク定義(JSON形式)の containerDefinitions 内にある secrets セクションを以下のように記述します。
{
"containerDefinitions": [
{
"name": "myapp-container",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:latest",
"secrets": [
{
"name": "DATABASE_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:myapp/production/db-xxxxxx:DB_PASSWORD::"
}
]
}
]
}
この設定により、コンテナ起動時にSecrets Managerの DB_PASSWORD に格納された値が、自動的に環境変数 DATABASE_PASSWORD としてコンテナ内にマッピングされます。
アプリケーションコードでの読み込み(補足)
この方法を採用した場合、コンテナ内では単に通常の環境変数を読み込むだけでよいため、外部のAWS SDKをインストールする必要はありません。Pythonであれば、標準ライブラリのみで以下のように簡単に実装できます。
import os
# AWS SDKは不要で、標準の環境変数として取得可能
db_password = os.environ.get("DATABASE_PASSWORD")
print(f"Password loaded successfully: {bool(db_password)}")
※もし、ECSのタスク定義連携を使わずに、コンテナアプリケーションから直接AWS SDKを使用してSecrets Managerから動的に値を取得したい場合は、あらかじめコンテナに以下のコマンドでAWS SDKを導入しておく必要があります。
pip install boto3
実務での注意点
1. タスク実行ロールとタスクロールを混同しない
ECSには似た名前の2つのIAMロールが存在し、初心者が最も混乱しやすいポイントです。
- タスク実行ロール(Task Execution Role):ECSエージェント(コンテナを起動・管理する仕組み)が使用するロール。Secrets Managerからの値の取得や、ECRからのイメージ取得に必要な権限を設定します(今回設定したのはこちらです)。
- タスクロール(Task Role):コンテナの中で実際に動いているアプリケーション自体が、S3やDynamoDBなどのAWSサービスにアクセスする際に使用するロール。
2. 最小特権の原則を遵守する
IAMポリシーを設定する際は、セキュリティリスクを抑えるため、Resourceを "*"(すべて)にせず、必ず特定のシークレットARNのみにアクセスを制限してください。また、シークレットを独自のKMSカスタマー管理キー(CMK)で暗号化している場合は、タスク実行ロールに kms:Decrypt 権限も付与する必要があります。
まとめ
本記事では、ECS環境においてSecrets Managerから安全に機密情報を取得する設定手順について解説しました。
ECSの secrets パラメータを利用することで、アプリケーションコードにAWSへの依存を持たせることなく、セキュアにデータベースの認証情報などを管理できるようになります。セキュリティと運用効率を両立させるため、ぜひ実務のインフラ構築で取り入れてみてください。