コンテンツにスキップ

ECS.16

検証日: 2026-04-25 / リージョン: ap-northeast-1

コントロールの説明

ECS タスクセット(TaskSet)にパブリック IP アドレスが自動的に割り当てられていないかをチェックする。AssignPublicIPENABLED に設定されている場合に 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.2ECS.16
対象リソースServiceTaskSet
デプロイメントコントローラーECS(デフォルト)EXTERNAL / CODE_DEPLOY
assignPublicIp の設定箇所サービスの networkConfigurationTaskSet の networkConfiguration

ECS.2 と同様に、assignPublicIp=ENABLED を設定できるのは Fargate 起動タイプのみである(公式ドキュメント)。また、assignPublicIp を省略した場合のデフォルト値は DISABLED である(API リファレンス、TaskSet でも同様であることを確認済み)。

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-disabledSecurity 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"
}

Amazonアソシエイトリンク