AWS Security Hubを有効化したところ、ECSタスク定義に関連するセキュリティリスクがいくつか検知されました。
今回は「ECSタスク定義の環境変数にデータベースのパスワードが平文で含まれている」というリスクに対応しました。
問題の内容
デプロイワークフローで、データベースパスワード(DB_PASSWORD
)をGitHub Secretsから読み込んで、ecspresso
を利用してECSタスク定義のenvironment
セクションへ渡していました。
機密情報をコードに直書きしていないので問題ないと思っていたのですが、Security Hubから「機密情報が平文でタスク定義に含まれている」という警告がきました。
環境変数に平文で含めていた設定例
GitHub Actionsのデプロイワークフローでは、次のようにDB_PASSWORD
を環境変数として設定し、それをecspresso
でデプロイ時にタスク定義へ反映していました。
GitHub Actions
- name: Setup environment
run: |
echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> $GITHUB_ENV
- name: Deploy to Company ECS service
run: ecspresso deploy --config ecspresso.yml
env:
ENV: ${{ env.DB_PASSWORD }}
ECSタスク定義
ecspresso
のテンプレートで以下のように、DB_PASSWORD
を環境変数にそのまま渡していました。
{
"containerDefinitions": [
{
"environment": [
{
"name": "DB_PASSWORD",
"value": "{{ must_env `DBPASSWORD` }}"
}
]
}
]
}
問題点
-
平文の機密情報がタスク定義に含まれる
- ECSタスク定義はAWS内部で保存されるため、アクセス権が適切に管理されていない場合や、デバッグログでタスク定義を出力してしまった場合などに、機密情報が漏洩するリスクがある
-
セキュリティのベストプラクティス違反
- AWSの推奨では、Secrets ManagerやSSM Parameter Storeを利用して機密情報を管理し、タスク定義には参照情報のみを含めるべきとされている
解決方法
機密情報を平文で直接タスク定義に含めないように、Secrets Managerを利用して安全にパスワードを管理する方法に切り替えました。
Secrets Managerの設定
1. Secrets Managerにシークレットを登録
Secrets Managerに以下のようなシークレットを登録しました。
- シークレット名:
dev/app/mysql/db
- 登録するキー/値の形式:
"DB_PASSWORD": "secure-password"
登録はコンソールかCLIから行えます。
CLIでの登録コマンド
aws secretsmanager create-secret \
--name dev/app/mysql/db \
--secret-string '{"DB_PASSWORD":"secure-password"}'
ECSタスク定義の修正
1. secrets
セクションでSecrets ManagerのARNを参照
Secrets Managerを利用して、DB_PASSWORD
を動的に取得できるように設定しました。
修正後のタスク定義の例
{
"containerDefinitions": [
{
"name": "app-container",
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:<region>:<account-id>:secret:dev/app/mysql/db:DB_PASSWORD::"
}
]
}
]
}
ecspressoを使った場合
ecspresso
ではテンプレートファイルでSecrets Managerを簡単に参照できます。secretsmanager_arn
テンプレート関数を利用することで、手動でARNを記載する必要がなくなります。
ecspressoのタスク定義テンプレート例
{
"containerDefinitions": [
{
"name": "app-container",
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "{{ secretsmanager_arn `dev/app/mysql/db` }}:DB_PASSWORD::"
}
]
}
]
}
IAMロール(タスク実行ロール)の設定
Secrets Managerの値を取得するには、ECSタスク定義で指定しているタスク実行ロールに適切な権限を付与する必要があります。
IAMポリシーの例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:dev/app/mysql/db"
}
]
}