Amazon ECS タスクおよびコンテナのセキュリティのベストプラクティス - Amazon Elastic Container Service

Amazon ECS タスクおよびコンテナのセキュリティのベストプラクティス

コンテナイメージは、攻撃に対する防御の最前線と見なしてください。安全性が低く、構築が不十分なイメージがあると、攻撃者はコンテナの境界を抜け出し、ホストにアクセスできるようになる可能性があります。これが発生するリスクを軽減するには、次のことを行う必要があります。

タスクとコンテナを設定するときは、次のことを行うことをお勧めします。

最小限のイメージを作成するか、distroless のイメージを使用する

まず、コンテナイメージから不要なバイナリをすべて削除します。Amazon ECR Public Gallery にある見慣れないイメージを使用している場合は、そのイメージを調べてコンテナの各レイヤーの内容を参照してください。これには Dive などのアプリケーションを使用できます。

あるいは、アプリケーションとそのランタイム依存関係のみを含む distroless イメージを使用することもできます。パッケージマネージャーやシェルは含まれません。Distroless イメージは、「スキャナーの信号対雑音比を向上させ、必要なものだけを調達する負担を軽減する」ことができます。詳細については、GitHub の distroless に関するドキュメントを参照してください。

Docker には、scratch と呼ばれる、予約済みの最小限のイメージからイメージを作成するメカニズムがあります。詳細については、Docker ドキュメントの「scratch を使用した単純な親イメージの作成」を参照してください。Go などの言語では、静的にリンクされたバイナリを作成して Dockerfile で参照できます。以下の例で、その方法を示します。

############################ # STEP 1 build executable binary ############################ FROM golang:alpine AS builder # Install git. # Git is required for fetching the dependencies. RUN apk update && apk add --no-cache git WORKDIR $GOPATH/src/mypackage/myapp/ COPY . . # Fetch dependencies. # Using go get. RUN go get -d -v # Build the binary. RUN go build -o /go/bin/hello ############################ # STEP 2 build a small image ############################ FROM scratch # Copy our static executable. COPY --from=builder /go/bin/hello /go/bin/hello # Run the hello binary. ENTRYPOINT ["/go/bin/hello"] This creates a container image that consists of your application and nothing else, making it extremely secure.

前の例も、マルチステージビルドの例です。これらのタイプのビルドは、コンテナレジストリにプッシュされる最終イメージのサイズを最小限に抑えることができるため、セキュリティの観点からは魅力的です。コンテナイメージからビルドツールやその他の無関係なバイナリを省くことで、イメージのアタックサーフェスが減り、セキュリティ対策を強化することができます。マルチステージビルドの詳細については、Docker ドキュメントの「Multi-stage builds」を参照してください。

イメージをスキャンして脆弱性がないか調べる

対応する仮想マシンと同様に、コンテナイメージには脆弱性のあるバイナリやアプリケーションライブラリが含まれていたり、時間の経過とともに脆弱性が生じたりする可能性があります。エクスプロイトから保護する最善の方法は、イメージスキャナーでイメージを定期的にスキャンすることです。

Amazon ECR に保存されている画像は、プッシュまたはオンデマンド (24 時間に 1 回) でスキャンできます。Amazon ECR のベーシックスキャンでは、オープンソースのイメージスキャンソリューションである Clair を使用します。Amazon ECR の拡張スキャンでは、Amazon Inspector を使用します。イメージがスキャンされると、その結果は Amazon EventBridge の Amazon ECR イベントストリームにログが残ります。また、Amazon ECR コンソール内から、あるいは DescribeImageScanFindings API を呼び出して、スキャンの結果を確認することもできます。脆弱性が HIGH または CRITICAL のイメージは、削除するか再構築する必要があります。デプロイされたイメージに脆弱性が生じた場合は、できるだけ早く交換する必要があります。

Docker Desktop Edge バージョン 2.3.6.0 以降では、ローカルイメージをスキャンできます。スキャンはアプリケーションセキュリティサービスの Snyk によって行われます。脆弱性が発見されると、Snyk は Dockerfile 内の脆弱性のあるレイヤーと依存関係を識別します。また、脆弱性が少なく、よりスリムなベースイメージを使用したり、特定のパッケージを新しいバージョンにアップグレードしたりするなど、安全な代替手段も推奨します。Docker スキャンを使用すれば、開発者はイメージをレジストリにプッシュする前に、潜在的なセキュリティ問題を解決できます。

イメージから特別な権限を削除する

アクセス権フラグsetuidsetgid は、実行ファイルの所有者またはグループの権限で実行できるようにします。これらのアクセス権限を持つバイナリは権限昇格に利用される可能性があるため、イメージからすべてのバイナリを削除してください。悪意のある目的に使用される可能性のある、nccurl などのシェルやユーティリティをすべて削除することを検討してください。次のコマンドを使用すると setuid および setgid アクセス権のあるファイルを見つけることができます。

find / -perm /6000 -type f -exec ls -ld {} \;

これらのファイルから、これらの特別な権限を削除するには、以下のディレクティブをコンテナイメージに追加します。

RUN find / -xdev -perm /6000 -type f -exec chmod a-s {} \; || true

キュレーションされたイメージのセットを作成する

開発者が独自のイメージを作成できるようにするのではなく、組織内のさまざまなアプリケーションスタック用に、検証済みのイメージセットを作成することができます。そうすることで、開発者は Dockerfile の作成方法を学ぶ必要がなくなり、コードの記述に集中できます。変更がコードベースにマージされると、CI/CD パイプラインがアセットを自動的にコンパイルし、アーティファクトリポジトリに保存できます。最後に、アーティファクトを適切なイメージにコピーしてから、Amazon ECR などの Docker レジストリにプッシュします。少なくとも、開発者が独自の Dockerfile を作成できるようなベースイメージのセットを作成する必要があります。Docker Hub からイメージをプルすることは避けてください。イメージに何が入っているかを常に把握できるわけではなく、上位 1000 個のイメージの約 5 分の 1 に脆弱性があります。これらのイメージとその脆弱性のリストは https://vulnerablecontainers.org/ で確認できます。

アプリケーションパッケージとライブラリをスキャンして脆弱性がないか調べる

オープンソースライブラリの使用は今や一般的になっています。オペレーティングシステムや OS パッケージと同様に、これらのライブラリには脆弱性が潜んでいる可能性があります。開発ライフサイクルの一環として、重大な脆弱性が見つかった場合は、これらのライブラリをスキャンして更新する必要があります。

Docker Desktop は Snyk を使用してローカルスキャンを実行します。また、オープンソースライブラリの脆弱性や潜在的なライセンス問題の検出にも使用できます。開発者のワークフローに直接統合できるため、オープンソースライブラリがもたらすリスクを軽減できます。詳細については、以下の各トピックを参照してください。

静的コード分析を行う

コンテナイメージを構築する前に、静的コード分析を実行する必要があります。これはソースコードに対して実行され、コーディングエラーや、フォールトインジェクションなどの悪意のある攻撃者に悪用される可能性のあるコードの特定に使用されます。Amazon Inspector を使用できます。詳細については、「Amazon Inspector ユーザーガイド」の「Amazon Inspector による Amazon ECR コンテナイメージのスキャン」を参照してください。

非ルートユーザーとしてコンテナを実行する

コンテナを実行するときは、非ルートユーザーとして実行してください。デフォルトでは、Dockerfile に USER ディレクティブが含まれていない限り、コンテナは root ユーザーとして実行されます。Docker によって割り当てられるデフォルトの Linux 機能では、root として実行できるアクションが制限されますが、制限されるのはごくわずかです。例えば、root として実行しているコンテナは、デバイスにアクセスすることがまだできません。

CI/CD パイプラインの一部として、Dockerfiles をリントして USER ディレクティブを探し、見つからない場合はビルドを失敗させる必要があります。詳細については、以下の各トピックを参照してください。

  • Dockerfile-lint は RedHat のオープンソースツールで、ファイルがベストプラクティスに準拠しているかどうかを確認するために使用できます。

  • Hadolint も、ベストプラクティスに準拠した Docker イメージを構築するためのツールです。

読み取り専用のルートファイルシステムを使用する

読み取り専用のルートファイルシステムを使用してください。コンテナのルートファイルシステムは、デフォルトでは書き込み可能です。コンテナに RO (読み取り専用) ルートファイルシステムを設定すると、データを保存できる場所を明示的に定義する必要性が生じます。これにより、権限が具体的に付与されない限りコンテナのファイルシステムに書き込みができなくなるため、アタックサーフェスが減少します。

注記

ルートファイルシステムが読み取り専用であると、そのファイルシステムへの書き込みが可能であることを想定している特定の OS パッケージで問題が発生する可能性があります。読み取り専用のルートファイルシステムを使用する予定がある場合は、事前に十分にテストしてください。

CPU とメモリの制限を設定してタスクを設定する (Amazon EC2)

以下のリスクを最小限に抑えるには、CPU とメモリの制限を設定してタスクを設定する必要があります。タスクのリソース制限は、タスク内のすべてのコンテナで予約できる CPU とメモリの量の上限を設定します。制限が設定されていない場合、タスクはホストの CPU とメモリにアクセスできます。これにより、共有ホストにデプロイされたタスクが他のタスクのシステムリソースを枯渇させるという問題が発生する可能性があります。

注記

Amazon ECS on AWS Fargate Tasks では CPU とメモリの制限を指定する必要があります。これらの値は請求目的で使用されるためです。Amazon ECS Fargate では、1 つのタスクがすべてのシステムリソースを占有しても問題にはなりません。各タスクは専有インスタンスで実行されるからです。メモリ制限を指定しない場合、Amazon ECS は各コンテナに最低 4MB を割り当てます。同様に、タスクに CPU 制限が設定されていない場合、Amazon ECS コンテナエージェントはタスクに最低 2 つの CPU を割り当てます。

Amazon ECR でイミュータブルタグを使用する

Amazon ECR では、イミュータブルタグを使用してイメージを設定することができるので、これを使用するようにしてください。これにより、変更または更新されたバージョンの画像が、同一のタグで画像リポジトリにプッシュされるのを防ぐことができます。また、攻撃者が侵害されたバージョンのイメージを同じタグが付いたイメージにプッシュすることを防ぐことができます。イミュータブルタグを使用すれば、変更するたびに異なるタグが付いた新しいイメージを効果的にプッシュできます。

コンテナを特権として実行することは避けてください (Amazon EC2)

コンテナを特権として実行することは避けてください。バックグラウンドでは、privileged として実行されるコンテナは、ホスト上で拡張された権限でされます。つまり、ホスト上で root に割り当てられた Linux 機能がすべてコンテナに継承されるということです。その使用は厳しく制限するか禁止してください。Amazon ECS コンテナエージェント環境変数 ECS_DISABLE_PRIVILEGEDtrue に設定して、privileged が必要がない場合はコンテナが privileged として特定のホストで実行されないようにすることをお勧めします。あるいは、AWS Lambda を使用してタスク定義をスキャンして privileged パラメータを使用することもできます。

注記

AWS Fargate 上の Amazon ECS では、コンテナを privileged として実行することはサポートされていません。

不要な Linux 機能をコンテナから削除する

Docker コンテナに割り当てられているデフォルトの Linux 機能のリストを以下に示します。各機能の詳細については、「Linux 機能の概要」を参照してください。

CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_FOWNER, CAP_FSETID, CAP_KILL, CAP_SETGID, CAP_SETUID, CAP_SETPCAP, CAP_NET_BIND_SERVICE, CAP_NET_RAW, CAP_SYS_CHROOT, CAP_MKNOD, CAP_AUDIT_WRITE, CAP_SETFCAP

コンテナが上記の Docker カーネル機能のすべてを必要としない場合は、それらをコンテナから削除することを検討してください。各 Docker カーネル機能の詳細については、「KernelCapabilities」を参照してください。次の操作を実行することで、どの機能が使われているかを確認できます。

  • OS パッケージ libcap-ng をインストールし、pscap ユーティリティを実行して各プロセスが使用している機能を一覧表示します。

  • capsh を使用して、プロセスが使用している機能を解読することもできます。

カスタマーマネージドキー (CMK) を使用して Amazon ECR にプッシュされるイメージを暗号化する

Amazon ECR にプッシュされるイメージの暗号化には、カスタマーマネージドキー (CMK) を使用してください。Amazon ECR にプッシュされたイメージは、保存時に AWS Key Management Service (AWS KMS) 管理キーで自動的に暗号化されます。独自のキーを使用したい場合は、Amazon ECR ではカスタマーマネージドキー (CMK) による AWS KMS 暗号化がサポートされています。CMK によるサーバー側の暗号化を有効にする前に、「保管データ暗号化」に関するドキュメントに記載されている考慮事項を確認してください。