Amazon ECSのセキュリティチェックは、ほとんどの場合、「コンテナがホストの権限をどの程度侵害できるか」、「外部インターネットに直接公開されているか」、「機密情報とログが安全に処理されているか」という点に集約できます。特にECSタスク定義(Task Definition)は、コンテナの実行方法、権限、ファイルシステム、環境変数、ログ設定がすべて含まれる重要なセキュリティポイントです。
AWSもECSタスクのネットワークモードに関して、特別な理由がない限りawsvpcネットワークモードの使用を推奨しており、Fargateタスクではawsvpcネットワークモードが必須です。

1. hostネットワークモードの使用を避けるべきである
ECSタスク定義でnetworkModeをhostに設定すると、コンテナがDockerの仮想ネットワークを迂回し、EC2ホストのネットワークネームスペースを直接使用するようになります。この場合、コンテナポートがホストのENIに直接マッピングされ、同じポートを複数のタスクが同時に使用できないという制約も生じます。
セキュリティの観点からはさらに重要です。hostネットワークモードは、コンテナとホスト間の隔離レベルを低下させます。一般的なウェブアプリケーション、APIサーバー、バックエンドサービスであれば、hostモードよりもawsvpcモードを使用する方が安全です。
推奨設定は以下の通りです。
{
"networkMode": "awsvpc"
}
##
2. ECSサービスのassignPublicIpはDISABLEDに設定すべきである
ECSサービスでassignPublicIpがENABLEDに設定されていると、タスクのENIにパブリックIPが自動的に割り当てられます。AWS Security HubのECSセキュリティ制御も、AssignPublicIPがENABLEDの場合は失敗と判断し、DISABLEDの場合は合格と判断します。
一般的な構造では、ECSタスクをプライベートサブネットに配置し、外部からのアクセスはALBやNLBを介して受けるのが良いでしょう。Fargateサービスもプライベートサブネットに配置し、パブリックIPを使用しない場合、アウトバウンドトラフィックはNAT Gatewayを介して出るように構成できます。
サービス設定の例は以下の通りです。
{
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": [
"subnet-private-a",
"subnet-private-b"
],
"securityGroups": [
"sg-ecs-service"
],
"assignPublicIp": "DISABLED"
}
}
}
3. pidModeをhostに設定すべきではない
pidModeをhostに設定すると、コンテナがホストのプロセスネームスペースを共有するようになります。この場合、コンテナ内部からホストのプロセスを見ることができ、状況によってはホストプロセスに影響を与える可能性があります。
AWS Security HubのECS.3制御は、ECSタスク定義がホストのプロセスネームスペースを共有しているかを確認し、コンテナがホストのPIDネームスペースを共有すると隔離効果が低下し、不正アクセスのリスクが高まると説明しています。
推奨設定は単純です。ほとんどの場合、pidModeをまったく指定しないか、少なくともhostに指定しないようにすればよいでしょう。
{
"pidMode": null
}
実際のタスク定義JSONでは、pidMode項目を省略するのが一般的です。
4. privilegedはtrueに設定すべきではない
privileged: trueは、コンテナにホストレベルの強力な権限を付与します。AWS Security HubのECS.4制御は、ECSタスク定義のコンテナ定義でprivilegedがtrueの場合に失敗と判断し、この設定がコンテナにホストコンテナインスタンスに対する昇格された権限を付与すると説明しています。
セキュリティ基準では、以下のように明示的にfalseを設定するのが良いでしょう。
{
"name": "app",
"image": "nginx:latest",
"privileged": false
}
特にECS on EC2環境では、privilegedコンテナはホスト侵害につながる可能性のある危険な設定です。Docker-in-Docker、セキュリティエージェント、特殊なシステムツールなど、本当に必要な場合を除き、使用しないのが原則です。
5. readonlyRootFilesystemをtrueに設定すべきである
readonlyRootFilesystem: trueは、コンテナのルートファイルシステムを読み取り専用に設定します。AWS Security HubのECS.5制御は、この値がfalseであるか、コンテナ定義にない場合に失敗と判断します。AWSは、この設定がコンテナインスタンスのルートファイルシステムが改ざんされたり書き込まれたりする攻撃ベクトルを減らし、最小権限の原則にも合致すると説明しています。
推奨設定は以下の通りです。
{
"name": "app",
"image": "nginx:latest",
"readonlyRootFilesystem": true
}
ただし、アプリケーションが/tmp、キャッシュディレクトリ、アップロードディレクトリなどに書き込み操作を行う必要がある場合は、別途ボリュームや一時ストレージパスを明確に設計する必要があります。ルートファイルシステム全体を書き込み可能にするのではなく、必要なパスのみを限定的に書き込み可能にする方法が良いでしょう。
6. 機密情報をenvironmentに直接含めるべきではない
ECSタスク定義のenvironmentにパスワード、アクセスキー、トークンなどの値を直接含めるのは危険です。AWSドキュメントでも、タスク定義に指定された環境変数は、そのタスク定義に対するDescribeTaskDefinition権限を持つユーザーとロールが読み取ることができると案内しています。
AWS Security HubのECS.8制御は、environment変数にAWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、ECS_ENGINE_AUTH_DATAのような機密キーが含まれているかを確認し、機密情報はParameter StoreやSecrets Managerを使用する方法を推奨しています。
悪い例は以下の通りです。
{
"environment": [
{
"name": "DB_PASSWORD",
"value": "plain-text-password"
}
]
}
推奨される方法はsecretsを使用することです。
{
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-2:123456789012:secret:prod/db/password"
}
]
}
ログ設定で機密オプションが必要な場合もsecretOptionsを使用でき、この値はSecrets ManagerまたはSystems Manager Parameter Storeに保存して参照できます。
7. logConfigurationを必ず設定すべきである
コンテナログが残らないと、障害分析、侵害調査、監査対応が非常に困難になります。AWS Security HubのECS.9制御は、最新のアクティブなECSタスク定義にlogConfigurationがない場合、またはコンテナ定義のlogDriver値がnullの場合に失敗と判断します。AWSは、ロギングがECSの信頼性、可用性、パフォーマンスの維持に役立ち、エラーの根本原因を見つけるために必要であると説明しています。
一般的なCloudWatch Logs設定の例は以下の通りです。
{
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/prod-app",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "ecs"
}
}
}
セキュリティ基準を反映したECSタスク定義の例
以下は、上記の基準を反映した代表的なFargate用ECSタスク定義の例です。
{
"family": "secure-ecs-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsAppTaskRole",
"containerDefinitions": [
{
"name": "app",
"image": "123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/app:latest",
"essential": true,
"user": "1000",
"privileged": false,
"readonlyRootFilesystem": true,
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{
"name": "APP_ENV",
"value": "production"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-2:123456789012:secret:prod/db/password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/secure-ecs-task",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
クイックチェックリスト
| 点検項目 | 推奨値 |
| networkMode | awsvpc |
| assignPublicIp | DISABLED |
| pidMode | host使用禁止 |
| privileged | false |
| readonlyRootFilesystem | true |
| 機密情報 | environment直接入力禁止、secrets使用 |
| ログ設定 | logConfiguration設定 |
## まとめ
ECSのセキュリティは複雑に見えますが、その核心は単純です。コンテナがホストと過度に共有しないようにし、外部インターネットに直接公開せず、機密情報とログを適切に扱うことです。
特に運用環境では、hostネットワークモード、pidMode: host、privileged: true、平文の環境変数、ログ未設定などの項目を優先的に排除する必要があります。これらの設定は単なる推奨事項ではなく、実際の侵害事故において攻撃者がコンテナからの脱出、資格情報の窃取、ログの回避を試みる際に頻繁に悪用される可能性のあるポイントです。
コメントを残す