Google Kubernetes Engine でのソフトウェア サプライ チェーンの保護

この記事では、コードを Google Kubernetes Engine(GKE)クラスタにデプロイする前に、ソフトウェア サプライ チェーンが既知の安全なパスをたどるようにする方法を説明します。この記事では、Binary Authorization の仕組みを確認してから、Google Cloud に Binary Authorization を実装して使用し、必須のステージごとの承認を確実に得るために可能な限り多くの情報がデプロイ パイプラインから得られるようにするための最適な方法を説明します。

ソフトウェア サプライ チェーン保護のビルディング ブロック

コンテナ化されたアプリケーションのビルドとデプロイでは、デプロイ単位として不変のアーティファクトを使用する必要があります。不変のアーティファクトは期待どおりに動作することがわかっているため、多くのホストや環境にソフトウェアをデプロイでき、拡張できます。

不変のアーティファクトを作成したら、バージョン管理や後で使用するためのカタログ化が可能なアーティファクト ストアに入れます。

リリース プロセスのさまざまな段階で、チェックポイントのシグナリングと同様に、アクティビティの結果を記述するメタデータを人の手や自動システムによって追加できます。たとえば、統合テストスイートに合格したことを示すメタデータをイメージに追加できます。

アーティファクトにメタデータを追加したら、インフラストラクチャにデプロイする前に合格する必要のある検証を定義する、デプロイ ポリシーを作成します。インフラストラクチャにメカニズムを構築し、承諾される前にワークロードが必須のチェックポイントすべてを通過することを検証します。この種の検証は、コードの実行が設定される直前に行われ、デプロイで必須のステージを回避できないようにします。

次の図に、ソフトウェア サプライ チェーン管理の一般的なプロセスを示します。

ソフトウェア サプライ チェーン管理プロセス

GKE におけるサプライ チェーンの保護

次の表に、サプライ チェーンのビルディング ブロックと Google Cloud の機能の比較を示します。

ビルディング ブロック Google Cloud の実装
不変のアーティファクト Docker イメージ
アーティファクト ストア Container Registry
アーティファクト メタデータ
アーティファクト監査者 認証者
アーティファクト検証 証明書
デプロイ ポリシー Binary Authorization ポリシー

デプロイする GKE の不変のアーティファクトは Docker イメージです。このイメージは一度ビルドされた後、アーティファクト ストアである Container Registry に push されます。ここで、任意の数の GKE クラスタにイメージをデプロイできるようになります。

Container Registry では、各メタデータを表すタグを使用してイメージに関する情報を追加します。イメージ上の Docker タグの最も一般的な用途は、v2.0.0beta など、ソフトウェアのバージョンやリリース トレインを示すことです。この情報は有用ですが、ビルドされた場所、ビルド元のソースコード、本番環境でのデプロイが承認されているかどうかなど、アーティファクトに関する詳細情報は、タグを使用して追加することはできません。このような詳細情報については、証明書を使用します。

認証者は、Container Registry 内のイメージに関するメモを追加することによって、イメージが特定の基準を満たすかどうかを示すことができます。このような情報には、イメージのライフサイクルを通じてアクセスできます。メモの種類の一部は分類されているため、イメージに関する情報をより的確にフィルタリングできます。メモの一種として、プロジェクトの認証者によって追加される attestation があります。たとえば、重大なセキュリティ上の脆弱性なしにイメージがビルドされたことや、特定のビルドシステムによってイメージがビルドされたことを検証する認証者があります。

関連付けられた Pretty Good Privacy(PGP)公開鍵をアップロードすることにより、認証者を作成および特定してプロジェクトに追加します。これにより認証者は、メッセージに署名することで証明書を作成できます。このメッセージは、認証者の証明対象である、コンテンツのアドレス指定が可能な特定のイメージ ダイジェストを特定するものです。

次の図は、特定のダイジェストのイメージに証明書を追加する例を示しています。

イメージへの証明書の追加

Binary Authorization を使用すると、ポリシーを構成して、クラスタ全体にデプロイする前にイメージに存在することが要求される証明書を定義できます。このポリシーは、イメージが重要な手順を省略せずにデプロイ パイプラインを介して正しいパスをたどるようにする、ビルディング ブロックを作成します。デプロイ パイプラインの重要な各ステージで、イメージがそのステップを通過したことを示す証明書を作成できます。証明書は、自動システムか、人の手で追加できます。

たとえば、イメージが品質保証(QA)チームによる検証に合格したことを確認するとします。テストが終了した後、QA チームメンバーの 1 人が特定のキーを使用して、認証者 qa-validated から証明書に署名します。この証明書は、プロダクション クラスタでイメージをデプロイするために必要です。

同様に、イメージが脆弱性についてスキャンされていて、異常が発生していないことを確認するとします。自動システムは、リポジトリ内の新しいイメージを監視し、特定の脆弱性基準を満たしているという証明書を追加できます。脆弱性スキャンを検証した後、システムは暗号鍵を使用して認証者 not-vulnerable から証明書に署名し、追加できます。この鍵を Cloud Key Management Service で暗号化して Cloud Storage に安全に保存し、Identity and Access Management で鍵へのアクセスを制御して、使用について Cloud Logging で監査できます。

次の図は、人と自動システムの認証者によって証明書が追加された Container Registry のイメージを示しています。

自動システムまたは人によって追加された Container Registry のイメージ

Binary Authorization を使用して、各証明書の検証に使用できる暗号鍵を定義するポリシーを作成します。allowlist に特定のイメージを追加して、証明書の検証をバイパスする、または特定のクラスタに対して Binary Authorization を無効にすることもできます。

Google Cloud では、ソフトウェア サプライチェーンの作成および管理のためのマネージド サービスを提供しますが、オープンソース実装を使用することで他の環境に同様のプロセスを実装することもできます。

次の表に、Google Cloud サービスと、同様の機能を提供するオープンソース ツールの比較を示します。

Google Cloud オープンソース
Container Registry Docker ディストリビューション
Metadata API Grafeas
Binary Authorization Kritis
脆弱性スキャン ClairAnchore Engine

継続的デリバリー パイプラインのベスト プラクティス

ソフトウェア サプライ チェーンの検証は、継続的デリバリー パイプラインがあり、自動化を使用してコード リポジトリから本番インフラストラクチャにソースコードをデプロイする場合に、最も効果的です。このようなパイプラインのステージは組織によって異なりますが、パイプラインがソフトウェアを安全にデプロイできるように、高水準のベスト プラクティスを実装できます。

一般的な CI / CD パイプライン ガイダンス

多くの組織では、個々のチームで独自の継続的デリバリー プロセスとツールを選択できます。この柔軟性によって自律性が高まり、チームは使い慣れたツールを使用できるようになりますが、すべてのリリースがベスト プラクティスに従うようにすることは難しくなるおそれがあります。Spinnaker のようなツールでチームのリリース パイプラインを一元管理する場合、単一の場所で、手法のテンプレート化、共有、監査ができるようになります。

イメージのビルド

他のサプライ チェーンと同様に、ソフトウェアの安全性は、実行可能なアーティファクトのビルドに使用するマテリアルと同程度しかありません。GKE を使用するときは、構築するイメージが安全なベースイメージから作成されていることを確認する必要があります。

ベースイメージのセキュリティを最大化する最初のステップは、アプリケーションの実行に必要なソフトウェアとライブラリのみを含む、最小限のディストリビューションを使用することです。Ubuntu、Debian、CentOS などの一般的なディストリビューションの場合、Google Cloud はセキュリティ パッチで定期的に更新されるマネージド ベースイメージを提供します。Distroless イメージは、さまざまなプログラミング言語で記述されたアプリケーションの実行に必要なライブラリとツールのみを含む、ベースイメージのセットです。ベースの選択後は、追加を最小限に抑えるようにしてください。Docker のマルチステージ ビルドを利用して、ランタイム依存関係とビルド時間依存関係を分離すると、攻撃対象となる部分を減らせます。

イメージをビルドしたら、組織のポリシーに準拠していることを確認します。コンテナ構造テストを作成すると、イメージの内容とメタデータを検証できます。また container-diff を使用して、既存のコンテナと新たにビルドされたコンテナを比較することもできます。

アプリケーション イメージに含めるものを絞り込んだら、クラスタで許可されているサードパーティ イメージのスコープを監査して縮小します。Binary Authorization を使用することで、証明書要件のバイパスが可能な allowlist にイメージを追加できます。必要でありながらアーティファクト作成パイプラインを介しては作成できないイメージのそれぞれについては、allowlist エントリができる限り詳細化されていることを確認します。

コンテナ構築の詳細については、コンテナ構築におすすめの方法のドキュメントをご覧ください。

イメージの脆弱性分析を有効にする

プロジェクトで Container Registry の脆弱性スキャンを有効にして、Docker イメージに潜在するセキュリティの問題に関する詳細情報を取得します。イメージが push されるとすぐに実行される自動スキャンは、イメージの脆弱性の重大度の把握に役立ちます。脆弱性はデプロイ前にチェックする必要がありますが、新たな脆弱性が見つかる可能性があるため、イメージはデプロイ後にもチェックする必要があります。脆弱性スキャンは、過去 30 日間にレジストリから取得されたイメージを継続的にスキャンします。イメージで脆弱性が見つかるたびに、Pub/Sub を使用することで通知を受け取れます

デプロイ時にポリシーを検証する

ソフトウェア サプライ チェーンを保護するには、デプロイ時にイメージ検証を有効にします。継続的デリバリー パイプラインの最後のステップであるデプロイは、プロセスにすべてのステージが含まれ、すべてのチェックポイントに合格したことを確認する良い機会です。このアプローチを採用すると、他のユーザーがクラスタの認証情報へのアクセスを入手しても、悪意のあるイメージはデプロイできなくなります。

Binary Authorization を使用すると、プロジェクト内のすべてのクラスタに対してデフォルト ルールを構成してから、それらのルールをクラスタ固有の構成でオーバーライドできます。 たとえば、すべてのクラスタで脆弱性スキャンと QA 検証の証明書を要求することもできますが、QA 検証に耐えることなくデベロッパーが development クラスタで新しいテクノロジーとイメージを試せるようにすることもできます。Binary Authorization ポリシーの詳細については、ポリシー YAML リファレンスのドキュメントをご覧ください。

パイプラインの例

ここでは、ビルドとデプロイという 2 つの主要なフェーズに分かれているパイプラインの例を示します。

サンプル パイプラインでのフェーズのビルドとデプロイ

次の表に、パイプラインの手順と証明書が追加される場所の詳細を示します。

ステップ番号 概要 説明 証明書
アイコン
1 ソースコードを取得する ビルドシステムで使用するために必要なリビジョンのソースコードをチェックします。 なし
2 単体テストを実施する アーティファクトを作成する前に、コードがすべての単体テストに合格していることを確認します。

単体テストを実施します。

3 Docker イメージを作成する ローカル ソースコードで Dockerfile を使用して、Container Registry にプッシュできるイメージをビルドします。 なし
4 Docker イメージがポリシーに準拠していることを確認する コンテナ構造テストを使用して、イメージのコンテンツが正しく、イメージ内のコマンドが正しい出力を返すことを確認できます。

Docker イメージがポリシーに準拠していることを確認します。

5 イメージを Container Registry に push する コードが単体テストされ、イメージのコンテンツが検証されると、イメージを Container Registry に push できます。脆弱性スキャンは自動的に開始されます。 なし
6 イメージに重大な脆弱性がないことを確認する 脆弱性スキャンは完了までに数分かかります。その後、表示されるすべての共通脆弱性識別子(CVE)に関するメモをイメージのメタデータに追加します。このデータが表示されるのを待ってから、重大な脆弱性が見つからない場合は証明書を追加します。

イメージに重大な脆弱性がないことを確認します。

7 イメージをステージングにデプロイする 変更を検証でき、できるだけ本番に近いシナリオで確認できる、本番前環境へのデプロイを開始します。

イメージをステージングにデプロイします。

8 本番環境にデプロイするコードを承認する 変更が要件を満たしていることをすべてのシグナルが示している場合、本番環境へのデプロイを承認します。 なし
9 本番クラスタのコードを適用する これで、クラスタ全体で更新するようにイメージを設定できます。各クラスタは、アプリケーションを実行する前にすべての証明書が完了していることを確認します。 なし

証明書の例

リリース パイプラインに含める証明書は、次のとおりです。

  • 脆弱性分析の結果に重大な脆弱性は含まれていなかった。
  • 手動 QA 検証に合格した。
  • イメージに含まれるソフトウェアはすべて適切にライセンスを付与されている。
  • アーティファクトは信頼できるビルドシステムで作成された。

次のステップ