Google Cloudとコンテナの継続的なセキュリティ
本文の内容は、2020年7月21日に Pawan Shankarが投稿したブログhttps://sysdig.com/blog/image-scanning-best-practices/)を元に日本語に翻訳・再構成した内容となっております。
本番環境でコンテナとKubernetesの実行を開始する場合でも、現在のDevOpsワークフローへより多くのセキュリティを組み込む場合でも、これらの12のイメージスキャンのベストプラクティスをお見逃しなく。
チームが直面する主な課題の1つは、アプリケーションの配信を遅らせずにセキュリティリスクを管理する方法です。これを早期に解決する方法は、Secure DevOpsワークフローを採用することです。
Secure DevOpsはDevSecOpsとも呼ばれ、開発から本番までのアプリケーションライフサイクル全体でセキュリティと監視を提供します。これにより、安全で安定した高性能のアプリケーションを提供できるようになります。このワークフローは、既存のツールチェーンにプラグインし、DevOps、開発者、およびセキュリティチーム全体に単一の信頼できる情報源を提供して、効率を最大化します。
イメージスキャンは、Secure DevOpsワークフローに組み込むための重要な機能です。防御の最前線の1つとして、脆弱性が悪用される前にそれを検出してブロックするのにも役立ちます。
幸いなことに、イメージスキャンは実装と自動化が簡単です。このブログでは、効果的なコンテナイメージスキャン戦略を採用するのに役立つ多くのイメージスキャンのベストプラクティスとヒントについて説明します。
イメージスキャンとは、セキュリティの問題、脆弱性、または悪い習慣を検出するために、コンテナイメージのコンテンツとビルドプロセスを分析するプロセスを指します。
ツールは通常、複数のフィード(NVD、Alpine、Canonicalなど)からCommon Vulnerabilities and Exposures(CVE)情報を収集して、イメージに脆弱性がないかどうかを確認します。最も一般的なセキュリティの問題と悪い習慣を探すために、すぐに使えるスキャンルールを提供するものもあります。
イメージスキャンは、Secure DevOpsワークフローのいくつかのステップに簡単に統合できます。たとえば、CI/CDパイプラインに統合して、脆弱性がレジストリに到達しないようにブロックしたり、レジストリでサードパーティのイメージの脆弱性から保護したり、実行時に新しく検出されたCVEから保護したりできます。
自動化され、ベストプラクティスに従っている場合、イメージスキャンにより、チームはアプリケーションのデプロイメントに時間がかかることがなくなります。
今日、実装できる12のイメージスキャンのベストプラクティスを詳しく見てみましょう。
コンテナイメージを作成するときは、公開する前に特に注意してスキャンする必要があります。
DevOpsワークフロー用にすでに構築しているCI/CDパイプラインを活用して、イメージスキャンを実行するための1つのステップを追加できます。
コードをテストしてビルドしたら、イメージを本番リポジトリにプッシュする代わりに、ステージングリポジトリにイメージをプッシュできます。次に、イメージスキャンツールを実行します。これらのツールは通常、見つかったさまざまな問題を一覧表示したレポートを返し、それぞれに異なる重大度を割り当てます。CI/CDパイプラインで、これらのイメージスキャン結果を確認し、重大な問題がある場合はビルドを失敗させることができます。
覚えておいてください、自動化が鍵です。これはDevOpsのコアコンセプトですよね?DevOpsの保護についても同様です。
CI/CDパイプラインへのセキュリティを自動化することにより、脆弱性がレジストリに入る前に脆弱性をキャッチすることができ、これらの問題や本番環境に到達する問題の影響を受ける機会を人々に与えることはありません。
前のステップでは、CI/CD パイプラインでのイメージスキャンが伝統的にステージングレジストリを含むことを見ました。しかし、イメージに誤って認証情報が含まれていたらどうでしょうか?それらが悪者の手に渡ってしまい、漏洩してしまう可能性があります。
さらに一歩進んで、インラインイメージスキャンを実装し、ステージングリポジトリを必要とせずにCI/CDパイプラインから直接イメージをスキャンすることができます。
インラインイメージスキャンでは、スキャンのメタデータのみがスキャンツールに送信されるため、プライバシーの管理が容易になります。
Gitlab、Github Actions、AWS Codepipeline、Azure Pipelines、CircleCI、Jenkins、Atlassian Bamboo、Tektonなど、最も一般的なCI/CDツールでインラインイメージスキャンを実装する方法について、いくつかのガイドを用意しました。
イメージスキャンの実装を開始するときは、最初のステップの1つとして、それをレジストリに含める必要があります。
デプロイするすべてのイメージは、レジストリから取得されます。そこでイメージをスキャンすることで、少なくとも実行前にイメージがスキャンされていることがわかります。
CI/CDパイプラインで脆弱なイメージをブロックしても、本番環境へのデプロイを妨げるものは何もありません。また、レジストリでスキャンされたとしても、外部の開発者からのイメージを誰がブロックするのでしょうか。
理想的には、イメージをスケジュールする前にKubernetesでイメージをチェックし、スキャンされていないイメージまたは脆弱なイメージがクラスターにデプロイされないようにする必要があります。
アドミッションコントローラを利用して、このポリシーを実装できます。
Kubernetesアドミッションコントローラは強力なKubernetesネイティブの機能であり、クラスターで実行できるものを定義およびカスタマイズするのに役立ちます。アドミッションコントローラは、リクエストが認証および承認された後、オブジェクトの永続化の前に、Kubernetes APIへのリクエストを傍受して処理します。
スキャンツールは通常、要求に応じて画像のスキャンをトリガーし、検証結果を返すことができるWebhookを提供します。
アドミッションコントローラは、イメージをスケジューリングする前にこのWebhookを呼び出すことができます。Webhookによって返されたセキュリティ検証の決定は API サーバに伝搬され、API サーバは元の要求者に返信し、イメージがチェックに合格した場合にのみ、オブジェクトをetcdデータベースに永続化します。
しかし、この判断は、クラスタ内で何が起こっているかについてのコンテキストを持たずにイメージスキャナによって行われます。OPAを使用することで、このソリューションを改善することができます。
Open Policy Agent (OPA) は、rego と呼ばれる高レベルの宣言言語を使用するオープンソースの汎用ポリシーエンジンです。OPAの背後にある重要なアイデアの1つは、意思決定をポリシーエンフォースメントからデカップリングすることです。
OPAを使えば、イメージスキャナではなく、Kubernetesクラスターでアドミッションの決定を行うことができます。このようにして、ネームスペースやポッドのメタデータなどのクラスタ情報を意思決定に利用することができます。例としては、"dev "ネームスペースに対して、より寛容なルールを持つポリシーと、"production "に対して非常に制限的なポリシーを持つことが考えられます。
スキャンするイメージが、Kubernetesクラスターにデプロイするイメージと異なる場合があります。これは、「latest」や「staging」などの可変タグを使用している場合に発生する可能性があります。このようなタグは常に新しいバージョンで更新されるため、最新のスキャン結果がまだ有効であるかどうかを知るのは困難です。
可変タグを使用すると、異なるバージョンのコンテナが同じイメージからデプロイされる可能性があります。スキャン結果のセキュリティ上の懸念を超えて、これはデバッグが困難な問題を引き起こす可能性があります。
例えば、ubuntu:focalを使用するのではなく、可能であれば、ubuntu:focal-20200423のような不変タグの使用を強制する必要があります。
(一部のイメージの)バージョンタグは、マイナーな、互換性のない変更で更新される傾向があることに注意してください。したがって、少し冗長に見えますが、再現性を保証する唯一のオプションは、実際のイメージIDを使用することです。
ubuntu:@sha256:d5a6519d9f048100123c568eb83f7ef5bfcad69b01424f420f17c932b00dea76
これはイメージスキャンのベストプラクティスを超えた問題だと考え始めているかもしれません。その通りです - Dockerfileのベストプラクティスのセットが必要です。これは、DockerfileのFROMコマンドだけでなく、Kubernetesのデプロイメントファイルや、イメージ名を付けるあらゆる場所に影響を及ぼします。
イメージスキャンの観点から何ができるでしょうか?
このポリシーは、Kubernetesアドミッションコントローラ、お使いのイメージスキャナ、そして先ほどのポイントで説明したシステムであるOPAエンジンの組み合わせを介して実施することができます。
一般的なイメージスキャンのベストプラクティスとして、この考えを心に留めておいてください。"イメージは軽ければ軽いほど良い。イメージが軽いということは、ビルドが速くなり、スキャンが速くなり、潜在的な脆弱性を持つ依存性が少なくなることを意味します。
新しいDockerイメージは通常、既存のベースイメージの上に構築されたり、レイヤーを追加したりします。このベースイメージはDockerfileのFROM文で定義されます。その結果、レイヤー化されたアーキテクチャ設計が実現され、最も一般的なタスクで多くの時間を節約することができます。例えば、イメージスキャンに関しては、ベースイメージを一度だけスキャンする必要があります。親イメージが脆弱であれば、その上に構築された他のイメージも脆弱になります。
たとえイメージに新しい脆弱性が介在していなかったとしても、ベースイメージにある脆弱性の影響を受けやすくなります。
そのため、スキャンツールは、既知の脆弱性のあるイメージの脆弱性フィードを積極的に追跡し、それらを使用している場合は通知してくれるはずです。
ディストロレスイメージとは、パッケージマネージャやシェルなど、標準的な Linux ディストリビューションに含まれていると思われるプログラムを含まないベースイメージのことです。ディストロレスイメージを使うと、アプリケーションとその依存関係のみを軽量なコンテナイメージにパッケージ化することができます。
ランタイムコンテナに含まれるものを必要なものだけに制限することで、攻撃対象を最小限に抑えることができます。また、スキャナのシグナル・ツー・ノイズ(CVEなど)を改善し、必要なものだけに証明性を確立する負担を軽減します。
下の例は、Ubuntu vs. distroless上で動作するgo "Hello world "アプリのDockerfileを示しています。
FROM ubuntu:focal COPY main /
ENTRYPOINT ["/main"]
スキャンした結果、24件のOSの脆弱性が見つかりました。そのうち2件は中程度の重大度です。また、このようなシンプルなアプリの場合、イメージサイズは77.98MBとかなり大きくなります。
さて、ディストロレスのイメージをベースにした同じアプリ:
FROM gcr.io/distroless/static-debian10 COPY main /
ENTRYPOINT ["/main"]
現在、重大度の低いOSの脆弱性は2つしか見つかりませんでした。また、イメージサイズは6.93MBに縮小されました。これは、このアプリに適しています。
これは、ディストロレスコンテナが不要なパッケージを持っていなかったことを示しており、より多くの脆弱性、ひいてはエクスプロイトが特定される可能性があります。
アプリケーションは多くのライブラリーを使用するため、チームが作成した実際のコードよりも多くのコード行を提供することになります。つまり、コードの脆弱性だけでなく、そのすべての依存関係の脆弱性にも注意する必要があります。
幸い、これらの脆弱性は、スキャナーがOSの脆弱性について警告するために使用するのと同じ脆弱性フィードで適切に追跡されます。すべてのツールがイメージ内のライブラリをスキャンするほど深くなるわけではないので、イメージスキャナーが十分に深く掘り下げ、それらの脆弱性について警告するようにしてください。
RUNDockerfileのコマンドに 注意する場合は、イメージをさらに最適化できます。RUNコマンドの順序は、イメージに適合するレイヤーの順序を決定するため、最終的なイメージに大きな影響を与える可能性があります。
大きなレイヤー(通常は不変)を最初に配置し、最も可変性の高いファイル(つまり、コンパイル済みアプリケーション)を最後に配置 することで、Dockerキャッシュの使用を最適化できます。これにより、既存のレイヤーの再利用、イメージの構築の高速化、および間接的にイメージのスキャン速度が向上します。
今見たように、Dockerイメージの構築プロセスは、マニフェストDockerfileからの指示に従います。
一般的なセキュリティの設定ミスを検出するために従うことができるDockerfileのベストプラクティスがいくつかあります。
このようなDockerfileでは:
FROM ubuntu:focal-20200423 USER root RUN curl http://my.service/?auth=ABD54F0356FA0054 EXPOSE 80/tcp EXPOSE 22/tcp
ENTRYPOINT ["/main"]
私たちのイメージスキャンは自動的にいくつかの問題を検出することができました:
USER root
ルートとして実行しています。
EXPOSE 22/tcp
ここでは、sshに一般的に使用されるポート22を公開しています。これは、コンテナに含めないツールです。ポート80も公開していますが、HTTPサーバーの一般的なポートと同様に、これで問題ありません。
RUN curl http://my.service/?auth=ABD54F0356FA005432D45D0056AF5400
このコマンドは、誰かが私たちに何らかの害を及ぼすために使用できる認証キーを使用します。代わりに、ある種の変数を使用する必要があります。このようなキーは、正規表現を使用して、Dockerfileだけでなく、イメージ内の任意のファイルでも検出できます。追加の手段として、資格情報を保存することがわかっているファイル名を確認することもできます。
これらのことに留意しなければならないことが多く、圧倒されてしまうこともあります。幸いなことに、これらのベストプラクティスのほとんどは、NIST や PCI などのセキュリティ基準でカバーされており、多くのイメージスキャンツールは、特定のコンプライアンスコントロールにマッピングされた、すぐに使えるポリシーを提供しています。
スキャンに合格したイメージは完全に安全ではありません。イメージをスキャンしてデプロイした直後に新たな脆弱性が見つかったとします。あるいは、ある瞬間にセキュリティポリシーを強化したとしますが、すでに実行中のイメージはどうなるでしょうか?
次の目的でイメージを継続的にスキャンすることがイメージスキャンのベストプラクティスです。
もちろん、ランタイムスキャンを実装することで、これらの脆弱性の影響を緩和することができます。CVE-2019-14287 を例に挙げてみましょう。この脆弱性が悪用されているかどうかを検出するための Falco ルールを簡単に書くことができます。しかし、それぞれの脆弱性に対して特定のルールを書くのは時間のかかる作業であり、最後の防衛線として使うべきです。
そこで、クラスター内で実行されているイメージを継続的にスキャンすることについて。
セキュリティツールはこれをアーカイブするために様々な戦略を用いていますが、最も単純なものは、数時間ごとにすべてのイメージを再スキャンすることです。理想的には、脆弱性フィードが更新されたらすぐに、影響を受けたイメージを再スキャンするのが良いでしょう。また、イメージのメタデータを保存できるツールもあり、完全な再スキャンを行わなくても新たな脆弱性を検出することができます。
そして、実行中のコンテナに脆弱性が見つかったら、できるだけ早く修正する必要があります。ここで重要なのは、効果的な脆弱性の報告を行うことで、各人が自分に関連する情報に集中できるようにすることです。
これを実現する一つの方法は、クエリー可能な脆弱性データベースを使用することで、DevOpsチームやセキュリティチームは、膨大なイメージ、パッケージ、および CVEのカタログの中にある程度の順序を置くことができます。チームは、CVEの年代、利用可能な修正プログラムの有無、ソフトウェアのバージョンなどのパラメータを検索したいと思うでしょう。最後に、これらのレポートをダウンロードして、脆弱性管理チームやCISOなどと共有(PDF/CSV)できると便利です。
例を挙げて説明しましょう。以下のようなクエリを想像してみてください。prod ネームスペースの中で、深刻度が高以上で、CVE が 30 日以上前のもので、修正プログラムが利用可能な脆弱性をすべて表示してください。
このような脆弱性レポート機能により、チームは脆弱性が悪用される前に、実際に修正できる脆弱なイメージを簡単に特定し、ソリューションの作業を開始できます。
オンプレミスソリューションよりもSaaSベースのスキャンサービスを選択すると、多くの利点があります。
オンデマンドでスケーラブルなリソース:最初にいくつかのイメージをスキャンすることから始め、コンテナアプリケーションのスケーリングに応じて拡張できます。バックエンドのデータ管理について心配する必要はありません。
迅速な実装: CI/CDパイプラインにスキャンを組み込んで、インストールとセットアップに時間がかかるオンプレミスアプリケーションとは異なり、数分で起動して実行できます。
簡単なアップグレードとメンテナンス: SaaSプロバイダーはパッチを処理し、手動でアップグレードする必要のない新機能の更新をロールアウトします。
インフラストラクチャーやスタッフのコストは不要:永続的な所有権を持つ社内のハードウェアおよびソフトウェアライセンスの支払いを回避できます。また、アプリケーションを保守およびサポートするためにオンサイトで作業する必要もありません。
イメージスキャンは、Secure DevOpsワークフローにおける最初の防御線です。自動化することで、潜在的な可能性を最大化し、問題になる前に問題を検出できます。イメージスキャンのベストプラクティスに従うと、速度を落とすことなくセキュリティを組み込むことができます。
また、イメージスキャンは一度適用するものではなく、構築時、レジストリ上、デプロイ前、コンテナがすでに実行されている場合など、ワークフローのいくつかの瞬間における継続的なチェックポイントです。
適切なツールを選択することが重要です。Sysdigには、インラインイメージスキャン、連続スキャン、脆弱性レポートなどの高度なイメージスキャン機能が含まれています。ガイド付きのオンボーディングを使用すると、5分未満で設定されます。今日それを試してみてください!