ECS.16
コントロールの説明
ECS タスクセット(TaskSet)にパブリック IP アドレスが自動的に割り当てられていないかをチェックする。AssignPublicIP が ENABLED に設定されている場合に FAILED となる。
ECS.2 との違い
ECS.2 はサービス(Service)の networkConfiguration をチェックするが、ECS.16 はタスクセット(TaskSet)の networkConfiguration をチェックする。
TaskSet は、Blue/Green デプロイ(CODE_DEPLOY)や外部デプロイメントコントローラー(EXTERNAL)を使用するサービスでのみ作成されるリソースである(公式ドキュメント)。デフォルトのデプロイメントコントローラー(ECS、ローリングアップデート)では TaskSet は作成されないため、通常の ECS 利用では本コントロールの評価対象リソースが存在せず、アカウントレベルで PASSED となる。
デフォルトの ECS コントローラーでは、サービス作成時にネットワーク設定(assignPublicIp 含む)を指定し、全タスクがその設定で起動する。一方、EXTERNAL / CODE_DEPLOY コントローラーでは、サービスの中に TaskSet を作成し、TaskSet ごとにネットワーク設定を指定する。
| ECS.2 | ECS.16 | |
|---|---|---|
| 対象リソース | Service | TaskSet |
| デプロイメントコントローラー | ECS(デフォルト) | EXTERNAL / CODE_DEPLOY |
| assignPublicIp の設定箇所 | サービスの networkConfiguration | TaskSet の networkConfiguration |
ECS.2 と同様に、assignPublicIp=ENABLED を設定できるのは Fargate 起動タイプのみである(公式ドキュメント)。また、assignPublicIp を省略した場合のデフォルト値は DISABLED である(API リファレンス、TaskSet でも同様であることを確認済み)。
assignPublicIp を省略した場合、デフォルトで DISABLED になることを確認済み。aws ecs create-task-set \
--cluster cspm-test-default \
--service cspm-test-default-svc \
--task-definition cspm-test-default:1 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[<SUBNET_ID>]}" \
--query 'taskSet.{id:id,assignPublicIp:networkConfiguration.awsvpcConfiguration.assignPublicIp}'{
"id": "ecs-svc/<TASK_SET_ID>",
"assignPublicIp": "DISABLED"
}対応する Config ルール: ecs-taskset-assign-public-ip-disabled(Security Hub カスタムルール、評価頻度: Configuration changes)
検証環境
--profile 指定がない場合は Workload アカウントで実行する。export AWS_PROFILE=Workload でデフォルトを設定しておくと便利。
結果
- TaskSet が存在しない場合、アカウントレベルで PASSED(ECS.2 とは異なり、対象リソースがなくても finding が生成される)
- EXTERNAL デプロイメントコントローラーのサービスで
assignPublicIp=ENABLEDの TaskSet を作成すると FAILED。TaskSet 削除後に finding は解消される - ECS.2 と同様に、
assignPublicIp=ENABLEDを設定できるのは Fargate 起動タイプのみ - 通常の ECS デプロイメントコントローラー(ローリングアップデート)では TaskSet は作成されないため、本コントロールが FAILED になることはない
- VPC BPA(宣言型ポリシー)を適用した場合の finding への影響は VPC Block Public Access を参照
検証の流れ
flowchart LR
A[1. 事前確認] --> B[2. FAILED の再現]
B --> C[3. Config トリガー<br>→ FAILED 確認]
C --> D[4. リソース削除]
D --> E[5. PASSED 復帰確認]
E --> F[6. クリーンアップ]
1. 事前確認
プロファイル確認
aws sts get-caller-identity --query '{Account:Account,Arn:Arn}'{
"Account": "<WORKLOAD_ACCOUNT_ID>",
"Arn": "arn:aws:sts::<WORKLOAD_ACCOUNT_ID>:assumed-role/<ROLE_NAME>/<SESSION_NAME>"
}Config ルール名の確認
aws configservice describe-config-rules \
--query "ConfigRules[?contains(ConfigRuleName, 'ecs-taskset')].{Name:ConfigRuleName,Trigger:Source.SourceDetails[0].MessageType}"[
{
"Name": "securityhub-ecs-taskset-assign-public-ip-disabled-<HASH>",
"Trigger": "ConfigurationItemChangeNotification"
}
]現在の Security Hub finding 確認
aws securityhub get-findings \
--filters '{
"ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "ECS.16"}],
"WorkflowStatus": [{"Comparison": "NOT_EQUALS", "Value": "SUPPRESSED"}]
}' \
--query 'Findings[].{ResourceId:Resources[0].Id,Status:Compliance.Status}'[
{
"ResourceId": "AWS::::Account:<WORKLOAD_ACCOUNT_ID>",
"Status": "PASSED"
}
]TaskSet が存在しないため、アカウントレベルで PASSED。
2. FAILED の再現
TaskSet を作成するには、外部デプロイメントコントローラー(EXTERNAL)を使用するサービスが必要。
ECS クラスター作成
aws ecs create-cluster \
--cluster-name cspm-test-cluster \
--query 'cluster.{clusterName:clusterName,status:status}'{
"clusterName": "cspm-test-cluster",
"status": "ACTIVE"
}タスク定義の登録
aws ecs register-task-definition \
--family cspm-test-task \
--network-mode awsvpc \
--requires-compatibilities FARGATE \
--cpu "256" \
--memory "512" \
--container-definitions '[{"name":"test","image":"public.ecr.aws/amazonlinux/amazonlinux:latest","essential":true}]' \
--query 'taskDefinition.{family:family,revision:revision,status:status}'{
"family": "cspm-test-task",
"revision": <REVISION>,
"status": "ACTIVE"
}サブネット ID の確認
aws ec2 describe-subnets \
--filters "Name=default-for-az,Values=true" \
--query 'Subnets[0].SubnetId' \
--output text<SUBNET_ID>EXTERNAL デプロイメントコントローラーのサービス作成
aws ecs create-service \
--cluster cspm-test-cluster \
--service-name cspm-test-svc-external \
--deployment-controller type=EXTERNAL \
--desired-count 0 \
--query 'service.{serviceName:serviceName,status:status,deploymentController:deploymentController.type}'{
"serviceName": "cspm-test-svc-external",
"status": "ACTIVE",
"deploymentController": "EXTERNAL"
}TaskSet 作成(assignPublicIp=ENABLED)
aws ecs create-task-set \
--cluster cspm-test-cluster \
--service cspm-test-svc-external \
--task-definition cspm-test-task:<REVISION> \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[<SUBNET_ID>],assignPublicIp=ENABLED}" \
--query 'taskSet.{id:id,status:status,networkConfiguration:networkConfiguration.awsvpcConfiguration.assignPublicIp}'{
"id": "ecs-svc/<TASK_SET_ID>",
"status": "ACTIVE",
"networkConfiguration": "ENABLED"
}3. Config トリガー → FAILED 確認
ECS.16 は Configuration changes 型のため、TaskSet 作成により自動的にトリガーされる。Config がリソースの Configuration Item を記録するまでに数分かかる場合がある。反映されない場合は手動トリガーを実行する。
Config ルールの手動トリガー(必要に応じて)
aws configservice start-config-rules-evaluation \
--config-rule-names securityhub-ecs-taskset-assign-public-ip-disabled-<HASH>(出力なし)Config 評価結果の確認
aws configservice get-compliance-details-by-config-rule \
--config-rule-name securityhub-ecs-taskset-assign-public-ip-disabled-<HASH> \
--compliance-types NON_COMPLIANT \
--query 'EvaluationResults[].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,Compliance:ComplianceType}'[
{
"ResourceId": "<TASK_SET_ARN>",
"Compliance": "NON_COMPLIANT"
}
]Security Hub finding の確認
Config → Security Hub の反映には追加で数分かかる。
aws securityhub get-findings \
--filters '{
"ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "ECS.16"}],
"ComplianceStatus": [{"Comparison": "EQUALS", "Value": "FAILED"}]
}' \
--query 'Findings[].{ResourceId:Resources[0].Id,Status:Compliance.Status,UpdatedAt:UpdatedAt}'[
{
"ResourceId": "<TASK_SET_ARN>",
"Status": "FAILED",
"UpdatedAt": "<TIMESTAMP>"
}
]4. リソース削除
TaskSet 削除
aws ecs delete-task-set \
--cluster cspm-test-cluster \
--service cspm-test-svc-external \
--task-set ecs-svc/<TASK_SET_ID> \
--force \
--query 'taskSet.{id:id,status:status}'{
"id": "ecs-svc/<TASK_SET_ID>",
"status": "DRAINING"
}5. PASSED 復帰確認
TaskSet 削除後、Config が設定変更を検知し、finding が解消される。数分待ってから確認する。
Config 評価結果の確認
aws configservice get-compliance-details-by-config-rule \
--config-rule-name securityhub-ecs-taskset-assign-public-ip-disabled-<HASH> \
--query 'EvaluationResults[].{ResourceId:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,Compliance:ComplianceType}'(出力なし — 対象リソースが存在しないため)Security Hub finding の確認
aws securityhub get-findings \
--filters '{
"ComplianceSecurityControlId": [{"Comparison": "EQUALS", "Value": "ECS.16"}],
"ComplianceStatus": [{"Comparison": "EQUALS", "Value": "FAILED"}]
}' \
--query 'Findings[].{ResourceId:Resources[0].Id,Status:Compliance.Status}'(出力なし — finding が解消されている)6. クリーンアップ
サービス削除
aws ecs delete-service \
--cluster cspm-test-cluster \
--service cspm-test-svc-external \
--force \
--query 'service.{serviceName:serviceName,status:status}'{
"serviceName": "cspm-test-svc-external",
"status": "DRAINING"
}タスク定義の登録解除
aws ecs deregister-task-definition \
--task-definition cspm-test-task:<REVISION> \
--query 'taskDefinition.{family:family,revision:revision,status:status}'{
"family": "cspm-test-task",
"revision": <REVISION>,
"status": "INACTIVE"
}タスク定義の削除
aws ecs delete-task-definitions \
--task-definitions cspm-test-task:<REVISION> \
--query 'taskDefinitions[0].{family:family,status:status}'{
"family": "cspm-test-task",
"status": "DELETE_IN_PROGRESS"
}ECS クラスター削除
aws ecs delete-cluster \
--cluster cspm-test-cluster \
--query 'cluster.{clusterName:clusterName,status:status}'{
"clusterName": "cspm-test-cluster",
"status": "INACTIVE"
}