イメージのセキュリティ - Amazon EKS

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

イメージのセキュリティ

コンテナイメージは、攻撃に対する防御の最前線と見なしてください。安全性が低く、構築が不十分なイメージがあると、攻撃者はコンテナの境界を抜け出し、ホストにアクセスできるようになる可能性があります。ホストになると、攻撃者は機密情報にアクセスしたり、クラスター内または AWS アカウントで横方向に移動したりできます。以下のベストプラクティスは、このような状況が発生するリスクを軽減するのに役立ちます。

レコメンデーション

最小イメージを作成する

まず、コンテナイメージから不要なバイナリをすべて削除します。Dockerhub の不慣れなイメージを使用している場合は、コンテナの各レイヤーの内容を表示できる Dive などのアプリケーションを使用してイメージを検査します。SETUID ビットと SETGID ビットを持つすべてのバイナリは、特権の昇格に使用できるため削除し、悪意のある目的に使用できる nc や curl などのシェルやユーティリティをすべて削除することを検討してください。SETUID ビットと SETGID ビットを持つファイルは、次のコマンドで確認できます。

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

これらのファイルから特別なアクセス許可を削除するには、コンテナイメージに次のディレクティブを追加します。

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

一方、これはイメージのファング解除と呼ばれます。

マルチステージビルドを使用する

マルチステージビルドの使用は、最小限のイメージを作成する方法です。多くの場合、マルチステージビルドは継続的インテグレーションサイクルの一部を自動化するために使用されます。たとえば、マルチステージビルドを使用してソースコードをリントしたり、静的コード分析を実行したりできます。これにより、デベロッパーはパイプラインの実行を待つ代わりに、すぐにフィードバックを得ることができます。マルチステージビルドは、コンテナレジストリにプッシュされる最終イメージのサイズを最小限に抑えることができるため、セキュリティの観点から魅力的です。コンテナイメージからビルドツールやその他の無関係なバイナリを省くことで、イメージのアタックサーフェスが減り、セキュリティ対策を強化することができます。マルチステージビルドの詳細については、Docker のマルチステージビルドドキュメントを参照してください。

コンテナイメージのソフトウェア部品表 (SBOMsを作成する

「ソフトウェア部品表」 (SBOM) は、コンテナイメージを構成するソフトウェアアーティファクトのネストされたインベントリです。SBOM は、ソフトウェアセキュリティとソフトウェアサプライチェーンのリスク管理における重要な構成要素です。SBOM を生成して中央リポジトリに保存し、SBOMs脆弱性をスキャンすると、次の問題に対処できます。

  • 可視性: コンテナイメージを構成するコンポーネントを理解します。中央リポジトリに保存すると、デプロイ後であってもいつでも SBOMs監査してスキャンし、ゼロデイ脆弱性などの新しい脆弱性を検出して対応できます。

  • Provenance Verification: アーティファクトの発生場所と発生方法に関する既存の前提が真であり、ビルドまたは配信プロセス中にアーティファクトまたは付随するメタデータが改ざんされていないことを確認します。

  • 信頼性: 特定のアーティファクトとそのコンテンツが、意図したとおりに動作するために信頼できることを保証します。つまり、 は目的に適しています。これには、コードを安全に実行できるかどうかの判断と、コードの実行に関連するリスクに関する情報に基づいた意思決定が含まれます。信頼度は、認証済みのパイプライン実行レポートと、認証済みの SBOM および認証済みの CVE スキャンレポートを作成して、このイメージが安全なコンポーネントで安全な手段 (パイプライン) を通じて実際に作成されることをイメージのコンシューマーに保証することで保証されます。

  • 依存関係の信頼検証: アーティファクトの依存関係ツリーを再帰的にチェックして、使用するアーティファクトの信頼性と出所を確認します。SBOMs のドリフトは、不正、信頼できない依存関係、侵入の試みなどの悪意のあるアクティビティを検出するのに役立ちます。

次のツールを使用して SBOM を生成できます。

  • Amazon Inspector を使用して SBOMs を作成およびエクスポートできます。

  • Anchore からの Syft は、SBOM の生成にも使用できます。脆弱性スキャンを迅速化するために、コンテナイメージ用に生成された SBOM をスキャンする入力として使用できます。SBOM とスキャンレポートは、レビューと監査の目的で Amazon ECR などの中央 OCI リポジトリにイメージをプッシュする前に、イメージにアタッチされます。

ソフトウェアサプライチェーンの保護の詳細については、CNCF Software Supply Chain Best Practices ガイドを参照してください。

イメージの脆弱性を定期的にスキャンする

仮想マシンと同様に、コンテナイメージには脆弱性のあるバイナリとアプリケーションライブラリが含まれているか、時間の経過とともに脆弱性が発生する可能性があります。エクスプロイトから保護する最善の方法は、イメージスキャナーでイメージを定期的にスキャンすることです。Amazon ECR に保存されているイメージは、プッシュまたはオンデマンド (24 時間に 1 回) でスキャンできます。ECR は現在、Basic と Enhanced の 2 種類のスキャンをサポートしています。ベーシックスキャンは、オープンソースのイメージスキャンソリューションである Clair を無償で活用します。拡張スキャンでは、Amazon Inspector を使用して、追加のコストで自動連続スキャンを提供します。イメージがスキャンされると、結果は EventBridge の ECR のイベントストリームに記録されます。ECR コンソール内からスキャンの結果を表示することもできます。高脆弱性または重大な脆弱性があるイメージは、削除または再構築する必要があります。デプロイされたイメージに脆弱性が生じた場合は、できるだけ早く交換する必要があります。

脆弱性のあるイメージがデプロイされている場所を把握することは、環境を安全に保つために不可欠です。イメージ追跡ソリューションを自分で構築することは可能ですが、これやその他の高度な機能をすぐに利用できる商用サービスが既にいくつかあります。

Kubernetes 検証ウェブフックを使用して、イメージに重大な脆弱性がないことを検証することもできます。検証ウェブフックは、Kubernetes API の前に呼び出されます。通常、ウェブフックで定義された検証基準に準拠していないリクエストを拒否するために使用されます。これは、ECR describeImageScanFindings API を呼び出して、ポッドが重大な脆弱性を持つイメージをプルしているかどうかを判断するサーバーレスウェブフックの例です。脆弱性が見つかった場合、ポッドは拒否され、CVEsされます。

認証を使用してアーティファクトの整合性を検証する

認証とは、パイプラインの実行、SBOM、脆弱性スキャンレポートなどの「述語」など、何かを主張する暗号で署名された「ステートメント」であり、別のモノ、「件名」、つまりコンテナイメージについて当てはまります。

認証は、ユーザーがアーティファクトがソフトウェアサプライチェーンの信頼できるソースから来ていることを検証するのに役立ちます。例えば、コンテナイメージには、そのイメージに含まれるすべてのソフトウェアコンポーネントや依存関係がわからない場合があります。ただし、コンテナイメージのプロデューサーがどのソフトウェアが存在するかを信頼する場合、プロデューサーの認証を使用してそのアーティファクトを信頼できます。つまり、自分で分析を行う代わりに、ワークフローでアーティファクトを安全に使用できます。

  • 認証は、AWS Signer または Sigstore 共同署名を使用して作成できます。

  • Kyverno などの Kubernetes アドミッションコントローラーを使用して、認証を検証できます。

  • コンテナイメージへの認証の作成やアタッチなどのトピックを含むオープンソースツールを使用した AWS でのソフトウェアサプライチェーン管理のベストプラクティスの詳細については、このワークショップを参照してください。

ECR リポジトリの IAM ポリシーを作成する

現在、組織が共有 AWS アカウント内で複数の開発チームを独立して運用することは珍しくありません。これらのチームがアセットを共有する必要がない場合は、各チームが操作できるリポジトリへのアクセスを制限する一連の IAM ポリシーを作成できます。これを実装する良い方法は、ECR 名前空間を使用することです。名前空間は、同様のリポジトリをグループ化する方法です。たとえば、チーム A のすべてのレジストリには team-a/ というプレフィックスを付けることができますが、チーム B のレジストリには team-b/ というプレフィックスを使用できます。アクセスを制限するポリシーは次のようになります。

{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPushPull", "Effect": "Allow", "Action": [ "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability", "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload" ], "Resource": [ "arn:aws:ecr:<region>:<account_id>:repository/team-a/*" ] } ] }

ECR プライベートエンドポイントの使用を検討する

ECR API にはパブリックエンドポイントがあります。したがって、リクエストが IAM によって認証および承認されている限り、ECR レジストリにはインターネットからアクセスできます。クラスター VPC にインターネットゲートウェイ (IGW) がないサンドボックス環境で操作する必要がある場合は、ECR のプライベートエンドポイントを設定できます。プライベートエンドポイントを作成すると、インターネット経由でトラフィックをルーティングするのではなく、プライベート IP アドレスを介して ECR API にプライベートにアクセスできます。このトピックの詳細については、「Amazon ECR インターフェイス VPC エンドポイント」を参照してください。

ECR のエンドポイントポリシーを実装する

のデフォルトのエンドポイントポリシーは、リージョン内のすべての ECR リポジトリへのアクセスを許可します。これにより、攻撃者/インサイダーはデータをコンテナイメージとしてパッケージ化し、別の AWS アカウントのレジストリにプッシュすることで、データを流出させることができます。このリスクを軽減するには、ECR リポジトリへの API アクセスを制限するエンドポイントポリシーを作成します。たとえば、次のポリシーでは、アカウント内のすべての AWS 原則が に対してすべてのアクションを実行し、ECR リポジトリに対してのみアクションを実行することを許可します。

{ "Statement": [ { "Sid": "LimitECRAccess", "Principal": "*", "Action": "*", "Effect": "Allow", "Resource": "arn:aws:ecr:<region>:<account_id>:repository/*" } ] }

AWS Organization の一部ではない IAM 原則によるイメージのプッシュ/プルを防ぐ新しいPrincipalOrgID属性を使用する条件を設定することで、これをさらに強化できます。詳細については、「aws:PrincipalOrgID」を参照してください。com.amazonaws.<region>.ecr.dkrcom.amazonaws.<region>.ecr.api エンドポイントの両方に同じポリシーを適用することをお勧めします。EKS は ECR から kube-proxy、coredns、aws-node のイメージをプルするため、レジストリのアカウント ID をエンドポイントポリシーのリソースのリストに追加するか、602401143452.dkr.ecr.us-west-2.amazonaws.com/ ポリシーを変更してアカウント ID からのプルを許可し、プッシュを制限する必要があります。次の表は、EKS イメージの提供元となる AWS アカウントとクラスターリージョン間のマッピングを示しています。

アカウント番号 リージョン

602401143452

以下に示すものを除くすべての商用リージョン

800184023465

ap-east-1 - アジアパシフィック (香港)

558608220178

me-south-1 - 中東 (バーレーン)

918309763551

cn-north-1 - 中国 (北京)

961992271922

cn-northwest-1 - 中国 (寧夏)

エンドポイントポリシーの使用の詳細については、「VPC エンドポイントポリシーを使用して Amazon ECR アクセスを制御する」を参照してください。

ECR のライフサイクルポリシーを実装する

NIST アプリケーションコンテナセキュリティガイドでは、「レジストリ内の古いイメージ」のリスクについて警告しています。誤ったデプロイや公開を防ぐために、古くて脆弱でout-of-dateソフトウェアパッケージを持つ古いイメージは、時間の経過とともに削除する必要があることに注意してください。各 ECR リポジトリには、イメージの有効期限が切れたときのルールを設定するライフサイクルポリシーを設定できます。AWS の公式ドキュメントでは、テストルールをセットアップし、評価して適用する方法について説明します。公式ドキュメントには、リポジトリ内のイメージをフィルタリングするさまざまな方法を示すライフサイクルポリシーの例がいくつかあります。

  • イメージの経過時間または数によるフィルタリング

  • タグ付きイメージまたはタグなしイメージによるフィルタリング

  • 複数のルールまたは単一のルールでのイメージタグによるフィルタリング

???+ 警告 長時間実行されているアプリケーションのイメージが ECR から消去されると、アプリケーションが再デプロイまたは水平スケーリングされると、イメージのプルエラーが発生する可能性があります。イメージライフサイクルポリシーを使用する場合は、デプロイとそれらが参照するイメージを最新の状態に保ち、リリース/デプロイの実行頻度を考慮した [イメージ] 有効期限ルールを常に作成するために、適切な CI/CD プラクティスが設定されていることを確認してください。

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

デベロッパーが独自のイメージを作成できるようにするのではなく、組織内のさまざまなアプリケーションスタック用に一連の審査済みイメージを作成することを検討してください。そうすることで、開発者は Dockerfile の作成方法を学ぶ必要がなくなり、コードの記述に集中できます。変更がマスターにマージされると、CI/CD パイプラインはアセットを自動的にコンパイルし、アーティファクトリポジトリに保存して、そのアーティファクトを適切なイメージにコピーしてから、ECR などの Docker レジストリにプッシュできます。少なくとも、開発者が独自の Dockerfile を作成する一連のベースイメージを作成する必要があります。理想的には、Dockerhub からイメージをプルしないようにします。イメージ内の内容が 1/ に常にわかっているわけではなく、上位 1000 イメージの 2/約 5 に脆弱性があるためです。これらのイメージとその脆弱性のリストは、こちらで確認できます。

非ルートユーザーとして実行する USER ディレクティブを Dockerfiles に追加する

ポッドセキュリティセクションで説明したように、コンテナをルートとして実行することは避けてください。これを podSpec の一部として設定できますが、Dockerfiles への USERディレクティブを使用することをお勧めします。USER ディレクティブは、USER ディレクティブの後に表示される RUNENTRYPOINT、または CMD命令を実行するときに使用する UID を設定します。

Dockerfiles をリントする

リンティングを使用して、Dockerfiles が一連の事前定義されたガイドラインに従っていることを確認できます。たとえば、 USER ディレクティブの包含や、すべてのイメージにタグを付けるという要件などです。dockerfile_lint は、一般的なベストプラクティスを検証する RedHat のオープンソースプロジェクトであり、Dockerfiles をリントするための独自のルールを構築するために使用できるルールエンジンが含まれています。これは CI パイプラインに組み込むことができます。ルールに違反する Dockerfile を使用してビルドすると、自動的に失敗します。

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 gitWORKDIR $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"]

これにより、アプリケーションとそれ以外で構成されるコンテナイメージが作成され、非常に安全になります。

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

イミュータブルタグは、イメージリポジトリへのプッシュごとにイメージタグを強制的に更新します。これにより、攻撃者がイメージのタグを変更せずに悪意のあるバージョンでイメージを上書きするのを防ぐことができます。さらに、イメージを簡単かつ一意に識別する方法も提供します。

イメージ、SBOMs、パイプライン実行、脆弱性レポートに署名する

Docker が最初に導入されたとき、コンテナイメージを検証するための暗号化モデルはありませんでした。v2 では、Docker はイメージマニフェストにダイジェストを追加しました。これにより、イメージの設定をハッシュし、ハッシュを使用してイメージの ID を生成できるようになりました。イメージ署名を有効にすると、Docker エンジンはマニフェストの署名を検証し、コンテンツが信頼できるソースから生成され、改ざんが行われていないことを確認します。各レイヤーがダウンロードされると、エンジンはレイヤーのダイジェストを検証し、コンテンツがマニフェストで指定されたコンテンツと一致することを確認します。イメージ署名により、イメージに関連付けられたデジタル署名の検証を通じて、安全なサプライチェーンを効果的に作成できます。

AWS Signer または Sigstore Cosign を使用して、コンテナイメージの署名、SBOMs の認証の作成、脆弱性スキャンレポート、パイプライン実行レポートを行うことができます。これらの認証により、イメージの信頼性と整合性が保証され、実際には干渉や改ざんなしで信頼できるパイプラインによって作成され、イメージパブリッシャーによって検証され、信頼されている (SBOM 内の) 文書化されたソフトウェアコンポーネントのみが含まれていることが保証されます。これらの認証は、コンテナイメージにアタッチしてリポジトリにプッシュできます。

次のセクションでは、監査とアドミッションコントローラーの検証に認証されたアーティファクトを使用する方法について説明します。

Kubernetes アドミッションコントローラーを使用した画像整合性の検証

動的アドミッションコントローラーを使用してターゲット Kubernetes クラスターにイメージをデプロイする前に、イメージ署名、認証済みアーティファクトを自動的に検証し、アーティファクトのセキュリティメタデータがアドミッションコントローラーポリシーに準拠している場合にのみデプロイを承認できます。

例えば、イメージの署名、認証された SBOM、認証されたパイプライン実行レポート、または認証された CVE スキャンレポートを暗号的に検証するポリシーを作成できます。CVE スキャンに重要な CVE がないなど、ポリシーに条件を記述してレポート内のデータを確認できます CVEs 。これらの条件を満たすイメージに対してのみデプロイが許可され、他のすべてのデプロイはアドミッションコントローラーによって拒否されます。

アドミッションコントローラーの例は次のとおりです。

コンテナイメージ内のパッケージを更新する

イメージapt-get update && apt-get upgrade内のパッケージをアップグレードするには、Dockerfiles に RUN を含める必要があります。アップグレードではルートとして実行する必要がありますが、これはイメージビルドフェーズ中に発生します。アプリケーションは root として実行する必要はありません。更新をインストールし、USER ディレクティブを使用して別のユーザーに切り替えることができます。ベースイメージが非ルートユーザーとして実行されている場合は、root と back に切り替えます。最新のセキュリティ更新プログラムのインストールは、ベースイメージのメンテナーだけに依存しないでください。

apt-get clean を実行して、 からインストーラファイルを削除します/var/cache/apt/archives/。パッケージをインストールrm -rf /var/lib/apt/lists/*した後に を実行することもできます。これにより、インデックスファイルまたはインストール可能なパッケージのリストが削除されます。これらのコマンドはパッケージマネージャーごとに異なる場合があることに注意してください。例:

RUN apt-get update && apt-get install -y \ curl \ git \ libsqlite3-dev \ && apt-get clean && rm -rf /var/lib/apt/lists/*

ツールとリソース