Google Cloudとコンテナの継続的なセキュリティ
本文の内容は、2022年4月7日現在における、Sysdig Cloud Native Learning Hub上のWhat Is Container Security?(https://sysdig.com/learn-cloud-native/container-security/what-is-container-security/) を元に日本語に翻訳・再構成した内容となっております。
コンテナセキュリティは、コンテナライフサイクルのすべての段階において、マルウェアやデータ漏洩などの脅威からコンテナを保護するプロセスです。コンテナイメージのビルドから、レジストリへのロード、本番環境へのデプロイまで、コンテナを潜在的な脅威から保護するためのツールやプロセスを実装する必要があります。
この記事では、コンテナライフサイクル全体にわたるコンテナセキュリティの管理について知っておく必要があるすべてのことを説明します。
コンテナセキュリティを理解するには、コンテナに影響を与える可能性のあるセキュリティの脅威を理解することから始まります。
これらの脅威は、ここで詳しく説明することができないほど多くの形態で現れます。しかし、最も一般的なコンテナセキュリティの脅威には、次のようなものがあります。
マルウェアは、コンテナ内にデプロイされる悪意のあるコードです。マルウェアは、コンテナライフサイクルのさまざまな段階でコンテナに潜り込むことができます。たとえば、CI/CD環境を侵害する攻撃者は、後にコンテナイメージをビルドするために使用されるソースコードリポジトリにマルウェアを挿入する可能性があります。また、攻撃者は、コンテナレジストリに侵入し、マルウェアを含む汚染されたイメージに置き換える可能性があります。コンテナ型マルウェアの3つ目のタイプは、ユーザーを騙して、外部ソースから悪意のあるコンテナイメージをダウンロードさせるという攻撃です。
いずれの場合も、コンテナの起動前に検出されなかったマルウェアがランタイム環境に侵入し、アプリケーションから機密データを収集したり、他のコンテナを妨害したりするなど、さまざまなセキュリティ上の問題を引き起こす可能性があります。
通常、コンテナは非特権モードで実行されるべきです。つまり、コンテナ化された環境の外側にある、自分が直接制御するリソースにアクセスすることはできないのです。コンテナ間の通信も、コンテナ同士が通信する理由がない限り制限する必要があります(たとえば、アプリケーションコンテナからログを収集するサイドカーコンテナを実行している場合など)。
コンテナが厳密に必要とされる以上の特権で実行されると、セキュリティリスクが生じます。安全でない特権は、通常、コンテナオーケストレーターの設定に問題があることが原因です。たとえば、Kubernetesによってオーケストレーションされたコンテナは、Kubernetesのセキュリティコンテキストとネットワークポリシーが適切に定義されていない場合、必要以上の特権を持つ可能性があります。
コンテナはデータを保存するために使用されることを意図していません。しかし、組織がコンテナイメージ内に機密情報を保存するというミスを犯すことがあります。例えば、Vineのソースコードは、Vineがプライベートだと思っていたコンテナレジストリが、一般にアクセス可能であり、ソースコードを含むイメージをホストしていることを誰かが発見したときに、すべて公開されました。(これは、コンテナ時代の比較的早い時期に起こったことで、コンテナイメージの管理に関するベストプラクティスがまだ十分に確立されていない時期でした。このようなミスが発生するのも無理はありません)。
このようなリスクを回避するために、企業はコンテナライフサイクルのすべての段階において、コンテナを保護するセキュリティ管理を実施する必要があります。以下では、各ステージの概要と、各ステージでチームが管理すべき脅威の種類を説明します。
コンテナのライフサイクルは、開発パイプラインから始まります。開発パイプラインは、後にコンテナに組み込まれるコードが生成される場所です。
前述のとおり、開発ツールを侵害した攻撃者は、ソースリポジトリに悪意のあるコードを挿入し、いわゆるソフトウェアサプライチェーン攻撃を引き起こす可能性があります。開発者がイメージの構築に使用する前に悪意のあるコードを検出しなければ、そのコードはパイプラインを伝って本番環境に流れ込む可能性があります。
開発ツールにアクセス制御を導入し、最小特権の原則を徹底することは、このリスクを防ぐのに有効です。また、ソースコードをビルドして出荷する前に、マルウェアがないかスキャンすることも有効です。
コンテナイメージとは、コンテナの実行に必要なコードを含むファイルです。イメージはコンテナそのものではなく、実行するコンテナのベースとなる青写真です。したがって、コンテナイメージの内容にマルウェアや機密データが含まれている場合、そのイメージから作成されるコンテナは安全ではなくなります。
前述のとおり、マルウェアがコンテナイメージに入り込まないようにするために、内部のソースコードをスキャンする必要があります。
しかし、コンテナイメージにはサードパーティのソースから取り込んだリソースが含まれることが多いため、自社のコードをスキャンするだけでは十分ではありません。また、コンテナスキャナを使用してコンテナイメージ全体をスキャンする必要があります。このスキャナーは、イメージの内容を評価し、安全でないことが分かっているコンポーネントにフラグを立てます。イメージスキャンは、あらゆる種類の脅威を検出できるわけではありませんが(特に、脆弱性データベースにまだ記録されていないカスタムマルウェアは検出を逃れる可能性があります)、既知の脅威の大部分について警告を発することができます。
コンテナイメージは作成後、通常コンテナレジストリに格納され、そこからユーザーがダウンロードできるようになります。
レジストリのセキュリティに対応するために、いくつかのベストプラクティスがあります。まず、許可されたユーザのみがレジストリ内のイメージにアクセスできるように、アクセス制御を実施する必要があります。こうすることで、イメージにプライベートなアプリケーションやデータが含まれている場合に発生する可能性のある、偶発的なデータ漏洩を防ぐことができます。
次に、レジストリを定期的に監査し、どのようなイメージが含まれているかを把握します。古いバージョンのアプリケーションを含む古いイメージは、攻撃対象領域を最小化するために削除する必要があります。
最後に、サードパーティのレジストリからコンテナイメージを使用する場合は、そのソースを信頼できることを確認してください。最も人気のあるパブリックなコンテナレジストリである Docker Hub にあるイメージの半分には、少なくとも 1 つのセキュリティ脆弱性が含まれています。また、攻撃者が意図的に悪意のあるイメージをアップロードし、疑うことを知らないユーザーを引きつけるような名前(mysqlimageやnginxappなど)にしている場合もあります。非公式なパブリックレジストリからイメージを取得することは避け、また、作成した組織に対する信頼度がどの程度であっても、すべてのイメージをスキャンするようにしてください。
コンテナ・ライフサイクルの最終段階はランタイムです。これは、レジストリからダウンロードしたコンテナイメージを使用して、コンテナが実環境にデプロイされるときです。
ランタイムセキュリティは、コンテナセキュリティの中でも最も複雑な側面の1つです。なぜなら、このセキュリティには複数の動的な仕組みが関わっており、使用するコンテナアプリケーションスタックの種類によって異なる可能性があるためです。しかし、ほとんどの場合、ランタイムセキュリティは、セキュリティの確保に基づいています。
コンテナのライフサイクルは、循環的かつ継続的なプロセスです。あるアプリケーションのコンテナが実行環境にデプロイされた後、アプリケーションが更新されると、サイクルは新たに始まり、新しいコンテナのセットがパイプラインにプッシュされます。新しいコンテナには、それぞれ新しいリスクが含まれている可能性があります。
このように、コンテナセキュリティは決して「set-it-and-forget-it」なものではありません。コンテナのライフサイクル全体にわたってリスクを継続的に監視し、監視ツール、脆弱性データベース、および設定を更新して、環境の進化に合わせてコンテナセキュリティのベストプラクティスを順守し続けなければなりません。