【Security Hub修復手順】[ECS.16] ECS タスクセットはパブリック IP アドレスを自動的に割り当てないでください。
こんにちは!コンサルティング部のみゃんです。
皆さん、お使いのAWS環境のセキュリティチェックはしていますか?
本記事では、AWS Security HubによるAWS環境のセキュリティ状況スコアリングに該当する項目についての修復手順をご紹介します。
本記事の対象コントロール
[ECS.16] ECS タスクセットはパブリック IP アドレスを自動的に割り当てないでください。
[ECS.16] ECS task sets should not automatically assign public IP addresses
前提条件
本記事はAWS Security Hubで「AWS基礎セキュリティのベストプラクティススタンダード」を利用されている方向けの内容となります。
AWS Security Hubの詳細についてはこちらのブログをご覧ください。
対象コントロールの説明
このコントロールは、Amazon ECSタスクセットにパブリック IPアドレスが自動的に割り当てられる設定になっていないかチェックします。タスクセットのネットワーク設定でAssignPublicIPをDISABLEDに設定すると、このコントロールは成功します。
タスクセットは、サービスのデプロイコントローラーをEXTERNALに指定した場合や、AWS CodeDeployによるBlue/Greenデプロイを利用した場合に作成されるリソースです。パブリック IPアドレスが割り当てられたタスクは、ネットワーク設定で許可されている場合、インターネットから直接到達可能になるため、想定していないアクセスや攻撃を受けるリスクがあります。特にBlue/Greenデプロイでは、新しいタスクセットが既存タスクセットのネットワーク設定を引き継ぐ仕様のため、一度パブリック IPが有効になると、デプロイを重ねるたびに設定が引き継がれ続けてしまいます。
パブリック IPアドレスによる直接到達性を許容すると、コンテナが意図しない第三者からのアクセスを受けるリスクがあるため、原則として修復を推奨します。
修復手順
コントロールの確認方法
- Security Hub CSPMコンソールを開く
- 左メニューから「検出結果」を選択
- フィルターで対象のコンプライアンスセキュリティコントロールID「ECS.16」を検索


ステークホルダーに確認
修復を行う前に、以下の点をステークホルダーに確認してください。
- 対象のタスクセットが、パブリック IPアドレスによる直接到達性を必要とする構成になっていないか(ALBやNAT Gatewayなど、他の経路で通信できないか)
- 対象サービスがBlue/Greenデプロイの実行中でないか(デプロイ中の変更は避ける)
タスクセットの運用方法によって、対応方法が異なるため、それぞれ修復手順をご案内します。
①AWS CodeDeployでBlue/Greenデプロイを運用している場合
まずはAWS CodeDeployでBlue/Greenデプロイを運用している場合の修復手順です。
新しいタスクセットは、デプロイ時に現在のプライマリタスクセットのネットワーク設定を引き継ぐ仕様です。AppSpecファイルでネットワーク設定を明示的に上書きすることで、次回以降のデプロイで作成されるタスクセットのパブリック IP割り当てを無効化できます。
ただし後述するように、インターネット経由でコンテナのイメージを取得している場合(パブリックリポジトリ等)、NAT Gatewayへルート設定されたプライベートサブネットを指定しないと、イメージの取得に失敗するため注意が必要です。
- 対象のデプロイグループで使用しているAppSpecファイルを開く
CodeDeployのデプロイ>アプリケーションを開き、対象のアプリケーション名を選択します。

デプロイタブから最新のデプロイの「リビジョンの場所」を押下します。

既存の「アプリの仕様」はバックアップをとっておきましょう。
次画面で使うので、コピーしておいてください。

Resources>TargetService>PropertiesにNetworkConfigurationを追加し、AssignPublicIpをDISABLEDに設定する
「デプロイの作成」を押下します。

対象のデプロイグループを選択し、リビジョンタイプは「AppSpecエディタの使用」を選択、AppSpec言語は「YAML」を選択します。
エディタ欄には先ほどコピーしたAppSpecの内容を貼り付けて、以下を修正します。

version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "{タスク定義ARN}"
LoadBalancerInfo:
ContainerName: "{コンテナ名}"
ContainerPort: {ポート番号}
NetworkConfiguration:
AwsVpcConfiguration:
Subnets: ["{サブネットID}"] →ここがInternetGatewayにルート設定されているサブネットの場合は、NAT Gatewayにルート設定されているサブネットのIDに修正する!!!
SecurityGroups: ["{セキュリティグループID}"]
AssignPublicIp: DISABLED ←ここがENABLEDになっていたらDISABLEDに修正する!!!
- 変更したAppSpecファイルを使用して、新しいデプロイを実行する
AssignPublicIp: DISABLEDに設定したら、「デプロイの作成」を押下します。

成功しました!

タスクセットが新しくパブリック IPを無効化したセットに置換され、古いタスクセットへはトラフィックが0になっています。

参考までに、置換された古いタスクセットが停止していることを確認します。
パブリック IPが割り当てられていることがわかります。

反対に新しいタスクセットが、実行中でかつパブリック IPが未割り当てであることを確認します。

①修復確認
Security Hub CSPMの画面で、コントロールポリシーの違反が解消されていることを確認します。
新規作成されたタスクセットは、コンプライアンスのステータスが「PASSED」になっていることを確認しました!

古い方のタスクセットは、停止済みのためコンプライアンスのステータスが「NOT_AVAILABLE」になっていることを確認しました。

①注意点 「Internet Gatewayにルート設定されたサブネットを指定していると、パブリック IPの無効化設定をして再デプロイした際にイメージ取得に失敗し、デプロイが失敗する」
修復手順の検証中に、AppSpecファイルのAssignPublicIpのみをDISABLEDに修正し、サブネットはパブリックサブネットのままにした場合どうなるかを検証しました。
検証環境では、Internet Gatewayへのデフォルトルートを持つパブリックサブネットにFargateタスクを配置し、インターネット上のパブリックリポジトリからコンテナイメージを取得していました。
しかし、AssignPublicIpをDISABLEDにすると、FargateタスクのENIにはパブリック IPが割り当てられません。パブリックサブネットに配置していても、プライベートIPv4アドレスのみを持つタスクは、Internet Gateway経由でインターネットへ直接通信できません。
その結果、パブリックリポジトリからコンテナイメージを取得できず、新しいタスクが起動しなかったため、CodeDeployのデプロイが失敗しました。

CodeDeployのエラー文 The deployment timed out while waiting for the replacement task set to become healthy. This time out period is 60 minutes. を見るとタイムアウトしていますね。
パブリック IPを無効化したタスクから、外部のパブリックリポジトリへ直接アクセスする必要がある場合は、NAT Gatewayへのデフォルトルートを持つプライベートサブネットにタスクを配置するなど、インターネットへのアウトバウンド経路を用意してください。
一方、コンテナイメージをAmazon ECRプライベートリポジトリに配置できる場合は、Amazon ECRやAmazon S3のVPCエンドポイントを使用し、インターネットを経由せずにイメージを取得する構成も検討できます。
②AWS CLIで直接タスクセットを管理している場合
ECSコンソール・CLIともに、既存タスクセットのネットワーク設定を直接編集する機能はありません。パブリック IPの割り当てを無効化した新しいタスクセットを作成し、プライマリタスクセットとして切り替えたあとに、古いタスクセットを削除します。
- パブリック IPを無効化した新しいタスクセットを作成する
aws ecs create-task-set \
--cluster {クラスター名} \
--service {サービス名} \
--task-definition {タスク定義} \
--scale "value=100,unit=PERCENT" \
--network-configuration "awsvpcConfiguration={subnets=[{サブネットID}],securityGroups=[{セキュリティグループID}],assignPublicIp=DISABLED}"
- 新しいタスクセットの
stabilityStatusがSTEADY_STATEになったことを確認する
aws ecs describe-task-sets \
--cluster {クラスター名} \
--service {サービス名} \
--task-sets {TaskSetのARN}

- 新しいタスクセットをプライマリタスクセットに切り替える
aws ecs update-service-primary-task-set \
--cluster {クラスター名} \
--service {サービス名} \
--primary-task-set {新しいタスクセットARN}

- パブリック IPが有効な古いタスクセットを削除する
aws ecs delete-task-set \
--cluster {クラスター名} \
--service {サービス名} \
--task-set {古いタスクセットARN}

②修復確認
修復後、Security Hubで検出結果が「PASSED」になることを確認します。

新規作成したタスクセットが「PASSED」、削除した古いタスクセットが「NOT_AVAILABLE」になっていることを確認します。

検知タイミングの差分について
今回2パターン検証しましたが、②AWS CLIで直接タスクセットを管理している場合はすぐ検知され、アラート状態になったのに対して、①AWS CodeDeployでBlue/Greenデプロイを運用している場合は約1日遅れで検知されました。
この差分について考察すると、②のパターンは明示的にCLIでタスクセットを作成しているのに対して、①はCodeDeploy下で行ったCreateServiceにより自動でタスクセットが作成されている点が影響しているかと思います。
①のパターンは、CreateTaskSetイベントがConfigのイベント履歴に記録されなかったことで、Configの即時検知にはならずに定期確認のタイミングで検知された可能性が高そうです。
ECS.16は変更トリガー型です。約1日の遅延は、AWS Configの記録頻度が「日次」だった場合や、Security Hub CSPMによる24時間以内の補完チェックなども考えられるため、上記はあくまで推測となります。
セキュリティチェックの実行スケジュール - AWS Security Hub
最後に
今回は、AWS Security HubによるAWS環境のセキュリティ状況スコアリングに該当する項目についての修復手順をご紹介しました。
コントロールを修正して、お使いのAWS環境のセキュリティをパワーアップさせましょう!
最後までお読みいただきありがとうございました!どなたかのお役に立てれば幸いです。
以上、みゃんでした!





