Amazon Web Services ブログ

Amazon ECRのネイティブなコンテナイメージスキャン機能について

本投稿は Richard Nguyen と Michael Hausenblas による寄稿を翻訳したものです。

コンテナセキュリティは、開発者、セキュリティ運用エンジニア、およびインフラ管理者を含む、さまざまなアクティビティとツールで構成されます。クラウドネイティブサプライチェーンの重要な要素の 1 つは、コンテナイメージをスキャンして脆弱性を検出し、そこから行動に移せる洞察を得ることです。 私たちはコンテナロードマップのIssue 17で、AWSネイティブソリューションを提供することがいかにお客様にとって重要であるかを学び、そして、ECRイメージスキャン機能を一般公開いたしました。この投稿では、ECR ネイティブのソリューションについて説明し、ユースケースの一つである「定期スキャン」の実装戦略を説明します。

Scanning 101

最初にコンテナスキャンに関する用語を解説し、前提知識を合わせましょう。 コンテナスキャンに精通している場合は、このセクションをスキップいただいても大丈夫です。

概念的には、コンテナセキュリティの一部としてのスキャンは次のようになります。

コンテナ化されたアプリケーションを見てみると、開発者(developer)がContinuous Integration(CI)パイプラインでコンテナイメージをbuildし、これらのアーティファクトをECRにプッシュしています。一方、セキュリティ運用エンジニア(secops)は、1つもしくは複数のECRリポジトリと、ECSやEKSなどのコンテナオーケストレーターを管理しています。この文脈でいうと、コンテナセキュリティは共同の責任であるということに着目することが重要で、developerと secops の役割は、クラウドネイティブのサプライチェーン全体のセキュリティに対処するために連携しています。たとえば、developerは、コンテナのUSER を定義し、イメージ内の不要なビルドツールを削除して攻撃対象領域を最小限に抑えるといった、セキュアなコンテナイメージをbuildするための推奨プラクティスに従います。同様に、secops も、runtimeポリシーを検証して適用するといったことを行ないます。

さらに、2種類のスキャンに分類することができます。

  • Static scanning (静的スキャン) :デプロイ前のフェーズで実行されるため、developers (もしくは secops) はコンテナが実行される前に脆弱性に気づくことができます。ECR イメージスキャン機能は、このカテゴリに分類され、コンテナイメージ内の OS パッケージをスキャンして、既知のセキュリティ上の脅威公開リストである共通脆弱性識別子 (CVE) を検出します。ECR イメージスキャン機能を利用すれば、独自のスキャンインフラを設定したり、サードパーティのスキャンライセンスを購入したりする必要はありません。
  • Dynamic scanning (動的スキャン):ランタイム環境で実行されるスキャンのことです。テスト環境、QA 環境、または本番環境で、すでに実行されているコンテナの脆弱性を特定することが可能であり、ビルド時点でインストール済みのソフトウェアに脆弱性が含まれていることが後日発覚した際や、ゼロデイの脆弱性なども検出可能です。動的(またはランタイム)コンテナセキュリティについては、CNCF Falcoなどのオープンソースソリューションから、Aqua SecurityTrend MicroTwistlock など、AWS コンテナコンピテンシーパートナーが提供するサービスまで、サードパーティ製のさまざまなオプションが利用可能です。

みなさまからお寄せいただいたフィードバックとさまざまな選択肢の評価結果に基づき、我々は人気のあるオープンソースプロジェクトであるCoreOS ClairをECRイメージスキャン機能で利用して脆弱性の静的解析を実行することに決定しました。イメージスキャン機能を備えるように ECR API、AWS CLI、SDK の拡張を行い、CI パイプラインやコマンドラインで使用しやすい形で、スケーラブルで信頼性の高いマネージドサービスを実装しました。

具体的な現実世界のユースケースから始めましょう。ECRでのコンテナイメージの定期スキャンです。

ユースケース: 定期スキャン

このユースケースでは、本番環境で使用されるコンテナイメージに対して定期スキャンを行います。あなたがsecopsの役割にあり、いくつかのECRリポジトリを管理しているとしましょう。イメージを手動でスキャンして、イメージスキャンの詳細な結果を調べるよりも、スキャン結果の概要の取得やリポジトリごとにドリルダウンする機能の方が必要でしょう。GitHubに利用可能なサンプルをまとめました。このサンプルでは、新機能であるイメージスキャン関連の ECR API を使用して、コンテナイメージの定期スキャンを実現し、使用例について順を追って説明していきます。

サンプルセットアップは 4 つの Lambda 関数で構成され、スキャン設定とイメージスキャンのスケジュールを管理するための HTTP API を提供し、スキャン設定を保存するためにS3 バケットを使用します。

ここではインストール部分をスキップし、一般的な使用シナリオに直接進みます。amazonlinux:2018.03centos:7ubuntu:16.04、およびubuntu:latestのコンテナイメージ用に aws ecr create-repository などで ECR リポジトリを作成し、それらの定期スキャンをスケジュールしたいと仮定しましょう。また、サンプルでは、HTTP API のベース URL が環境変数ECRSCANAPI_URLを介して利用可能であることを前提としています。

デモで使用されるサンプルスキャン設定(この例では16.04とlatestのタグが付けられたUbuntuイメージの場合)は、次のようになります。

{
    "region": "us-west-2",
    "registry": "123456789012",
    "repository": "test/ubuntu",
    "tags": [
        "16.04",
        "latest"
    ]
}

次のコマンドを使用して、スキャン設定を登録し、Ubuntuイメージの定期スキャンを有効にします。

$ curl -s --header "Content-Type: application/json" \
          --request POST \
          --data @scan-config-ubuntu.json \
          $ECRSCANAPI_URL/configs/

上記と同じ URLである $ECRSCANAPI_URL/configs/に対して HTTP GET でリクエストすると、登録されているすべてのスキャン設定が一覧表示されます。

さあ、いよいよスキャン結果概要を見てみる時です。これは、次のコマンドによって利用できます。

$ curl $ECRSCANAPI_URL/summary
Results for amazonlinux:2018.03 in us-west-2:

Results for test/centos:7 in us-west-2:
 HIGH: 7
 LOW: 7
 MEDIUM: 20

Results for test/ubuntu:16.04 in us-west-2:
 INFORMATIONAL: 19
 LOW: 24
 MEDIUM: 8

Results for test/ubuntu:latest in us-west-2:
 MEDIUM: 7
 INFORMATIONAL: 9
 LOW: 13

この結果を見て、おそらくあなたは、最初に緊急度 HIGH の検出結果から取り組んでいくでしょう。$ECRSCANAPI_URL/findings/$scanIDを使用して、特定のリポジトリの詳細な結果を Atom フィードのフォーマットで取得することが可能です。

上記のスクリーンショットからわかるように、緊急度とイメージタグでフィルタリングして、個々の調査結果をドリルダウンして確認することができます。一点注意していただきたいのは、このサンプルは本番環境で即座に利用可能とすることよりも、コンセプトの証明(PoC)を行うことを目的に作られたものであるということです。とはいえ、この新しい ECR API をどのように使うかというアイデアをお見せすることで、あなた自身が構築する上でのインスピレーションとなり得るはずです。

最後に、ここではデモ目的として再スキャン間隔を5分に設定しているため、結果がすぐに表示されています。実際のデプロイでは、最大で1日に1回定期スキャンとするのが良いでしょう。これについては以下で詳しく説明します。

スキャンと検出結果

ECR イメージスキャン機能は、scan-on-pushとscan-on-demandの2つのモードをサポートします。

scan-on-pushを使用する場合は、リポジトリの作成時にscanOnPush=trueを次のように指定できます。

$ aws ecr create-repository --repository-name example \
                            --image-scanning-configuration \
                            scanOnPush=true
{
    "repository": {
        "repositoryArn": "arn:aws:ecr:us-west-2:123456789012:repository/example",
        "repositoryUri": "123456789012.dkr.ecr.us-west-2.amazonaws.com/example",
        "createdAt": 1469492686.0,
        "repositoryName": "example",
        "registryId": "123456789012",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": true
        }
    }
}

また、aws ecr put-image-scanning-configurationコマンドを利用することで、リポジトリが作成された後にscan-on-pushを有効にすることもできます。このモードでは、コンテナイメージが ECR リポジトリにプッシュされるたびに、スキャンがトリガーされ、結果は通常ほんの数秒で利用できます。

アドホックなスキャンや上記デモでお見せした定期スキャンのようなオンデマンドなスキャンを行う場合は、次のコマンドを利用できます。

$ aws ecr start-image-scan --registry-id 123456789012 \
                           --repository-name example \
                           --image-id imageTag=latest

スキャンの進行中に、あらためてstart-image-scanコマンドを実行しても、新しいスキャンはトリガーされないことに注意してください。

scan-on-pushまたはscan-on-demandのどちらを使用している場合でも、スキャン結果を取得するには、次のコマンドを使用します(リポジトリとイメージタグの両方を指定します)。

$ aws ecr describe-image-scan-findings --registry-id 123456789012 \
                                       --repository-name example \
                                       --image-id imageTag=latest
{
    "registryId": "123456789012",
    "repositoryName": "example",
    "imageId": {
        "imageTag": "latest",
        "imageDigest": "sha256:1bbdea4846231d91cce6c7ff3907d26fca444fd6b7e3c282b90c7fe4251f9f86"
    },
    "imageScanStatus": {
        "status": "COMPLETED",
        "description": "The scan was completed successfully."
    },
    "imageScanFindings": {
        "imageScanCompletedAt": 1541184040.0,
        "vulnerabilitySourceUpdatedAt": 1541184040.0,
        "findingSeverityCounts": {
            "MEDIUM": 7,

使用方法や返されたペイロードの、より詳細な情報については、ECRのドキュメントを参照してください。

カバレッジとコスト

ECR イメージスキャンでどのような機能が提供されるかを理解できたかと思いますので、続いてカバレッジとコストに関する質問に触れていきましょう。

現時点では、ECR は、Debian、Ubuntu、Amazon Linux を含むほとんどの一般的な Linux ディストリビューションで、オペレーティングシステム (OS) パッケージの CVE スキャンを提供しています。最新のリストについては、ドキュメントを参照してください。言語ライブラリ(Java、Python、Node.js等)など、コンテナ化されたアプリケーションが依存する他のタイプのパッケージのスキャンは現在スコープ外です。

イメージスキャンを皆様の開発ワークフローの一部としていただけるように、ECR サービスクォータを考慮しつつ追加料金なしで提供しており、すべてのユーザーに公正で信頼できるスキャン機能を体験いただけるようにしています。例えばイメージスキャンにおいては、イメージごとに24時間単位で1スキャンのスロットルを実装しており、この期間で同じイメージを複数回スキャンすると、ThrottlingExceptionが発生します。

これに関連して、定期スキャンを最大で 1 日に 1 回頻度にすることを推奨します。定期スキャンはゼロデイの脆弱性(コンテナイメージがビルド、または ECR にプッシュされた時点では未発見であったもの)に対処するために有益ですが、それらを修正にあたっては脆弱性の発生(とその頻度)、脆弱性が見つかってから対応が済むまでの時間を考慮に入れなければなりません。

次のステップ

本日、ECR の重要な機能をローンチできたことを嬉しく思います。この機能を活用して、コンテナ化されたアプリケーションのセキュリティ体制を改善できることを願っています。コンテナのロードマップを通じてコンテナのイメージスキャン機能をどこで、どのように使用しているかを学びたいと思っていますし、他にもあると便利だと思われる機能についてのフィードバックを(できれば具体的なユースケースと一緒に)いただけると幸いです。

翻訳はソリューションアーキテクト濵が担当しました。原文はこちらです。