Cloud Build と Artifact Registry による最小権限の原則の実践
Google Cloud Japan Team
※この投稿は米国時間 2022 年 11 月 4 日に、Google Cloud blog に投稿されたものの抄訳です。
Cloud Build と Artifact Registry による最小権限の原則の実践
ユーザーは多くの場合、ソフトウェア アーティファクトのビルドと保存のために Cloud Build と Artifact Registry を併用します。これにはもちろんコンテナ イメージが含まれていますが、OS パッケージや言語固有のパッケージも含まれています。
これらのユーザーが、Google Cloud プロジェクトを共有のマルチテナント環境で使用しているユーザーでもあることを示すベン図を思い浮かべてみてください。プロジェクトは Cloud Build や Artifact Registry などのサービスを論理的にカプセル化したものなので、これらのサービスの管理者はほとんどの場合に、最小権限の原則を適用することを希望します。
この原則には多くの利点がありますが、構成の誤りや悪意のあるユーザーによる被害の範囲が小さくなることが、おそらく最も重要でしょう。
ユーザーやチームは、Cloud Build や Artifact Registry を互いに中断や損害を与えることなく安全に使用できる必要があります。
このような環境を、Cloud Build のトリガー単位のサービス アカウントや、Artifact Registry のリポジトリ単位の権限によって実現する方法について解説します。
従来の方法
デフォルトのシナリオとして、最小権限の原則を適用する前の状態を考えてみましょう。このシナリオでは、Cloud Build トリガーをリポジトリに接続しています。
ソースコード リポジトリでイベントが発生すると(変更をメインブランチに結合するなど)、このトリガーが起動され、Cloud Build でアーティファクトのビルドが開始されて、その後でアーティファクトが Artifact Registry に push されます。
しかし、このワークフローでの権限にはどのような意味があるのでしょうか。そこで、権限スキームを調べてみましょう。特に指定していなければ、トリガーは Cloud Build のデフォルト サービス アカウントでビルドを実行します。このサービス アカウントにデフォルトで与えられるいくつかの権限の中に、プロジェクト レベルの Artifact Registry 権限があります。
ビルドは、特に指定されていなければ、このサービス アカウントを ID として実行されます。すなわち、これらのビルドは Google Cloud プロジェクト内の Artifact Registry にある任意のアーティファクト リポジトリと連携できます。次に、そのセットアップ方法について見てみましょう。
具体的な作業
このシナリオでは、下のワークフローをセットアップする手順について解説します。ここでは、Cloud Build のビルドトリガーが GitHub リポジトリに接続されています。これを実演するには、リポジトリがセットアップされ、Cloud Build に接続されている必要があります。方法についてはここを参照してください。変数名は自分で独自の値に置き換える必要があります。
このビルドトリガーは、このリポジトリのメインブランチに変更が起きると、ビルドを開始します。ビルド自体はコンテナ イメージをビルドして、Artifact Registry に push します。
実装の詳細としてここで重要なのは、このトリガーによるすべてのビルドでは、Artifact Registry 内の特定のリポジトリに対する権限しかない専用のサービス アカウントが使用されるという点です。
まず、架空のチームである Team A のコンテナ イメージ用の Artifact Registry リポジトリを作成します。
次に、Team A 用のサービス アカウントを作成します。
次が面白い部分です。このサービス アカウントと、前に述べた Artifact Registry リポジトリとの間に IAM ロールのバインディングを作成します。以下に、これを gcloud で行う方法を例として示しています。
これにより、artifactregistry.writer
ロールに付属する権限がそのサービス アカウントに与えられますが、これは特定の Artifact Registry リポジトリに対してのみとなります。
Cloud Build では以前からすでに、手動で実行されるビルドについて、ユーザーがビルド仕様で使用する特定のサービス アカウントを指定できるようになっています。この例は、以下のビルド仕様で見ることができます。
しかし多くのチームにとっては、ビルドの実行を自動化し、チームとシステムが利用するコードと構成の流れに組み入れることが不可欠です。このためには、Cloud Build のトリガーを使用します。
Cloud Build でトリガーを作成するときは、ソースコード リポジトリに接続するか、独自の Webhook をセットアップします。ソースが何であっても、トリガーが依存するのは、Identity and Access Management を使用して Google Cloud プロジェクト内でコントロールできる権限の対象範囲外のシステムです。
今度は、Git リポジトリでビルドトリガーを使用するとき、最小権限の原則を適用しないと何が起きるかを考えてみましょう。
どのようなリスクを軽減すべきでしょうか。
ソフトウェア アーティファクトのためのサプライ チェーン レベル(SLSA)セキュリティ フレームワークは、ソフトウェアのサプライ チェーン、本質的にはコードの作成、テスト、ビルド、デプロイ、実行における潜在的な脅威を詳細に示したものです。
脅威 B にあるように、侵入されたソース リポジトリに基づいてトリガーがビルドを開始すると、その影響がダウンストリームでどのように広がるかを見ることができます。侵入されたリポジトリのアクションに基づいてビルドが実行されると、それ以後にいくつもの脅威が発生します。
これらのビルドが持つ権限を最小に抑えることで、侵入されたソース リポジトリの及ぼす影響の範囲を減らすことができます。このチュートリアルでは、脅威 G の侵入されたパッケージ リポジトリの影響を最小化することに絞って説明します。
ここで示す例では、ソース リポジトリが侵入された場合、作成される特定の Artifact Registry リポジトリのパッケージのみが影響を受けます。トリガーと関連付けられているサービス アカウントには、その 1 つのリポジトリに対する権限しか与えられていないためです。
専用のサービス アカウントでビルドを実行するトリガーを作成するには、追加のパラメータが 1 つだけ必要です。例として gcloud を使用するなら、–-service-account
のパラメータを次のように指定します。TEAM_A_REPO
は、前の手順で作成して Cloud Build に接続した GitHub リポジトリです。TEAM_A_REPO_OWNER
はリポジトリ オーナーの GitHub ユーザー名で、TEAM_A_SA
は前の手順で作成したサービス アカウントです。それ以外に、そのリポジトリの cloudbuild.yaml
マニフェストを指定すれば、トリガーがセットアップされます。
トリガーがセットアップされたので、このトリガーに基づいて実行されるビルドの権限の範囲をテストし、Artifact Registry で TEAM_A_REPOSITORY
を操作するための権限しか保有していないことを確認できます。
まとめ
ビルドトリガーに最小権限を構成するのは、より大きなセキュリティ全体像の一部でしかありませんが、ソフトウェアのサプライ チェーンのセキュリティを保護する作業のどの段階においても有効な手順です。
さらに詳しい情報については、SLSA セキュリティ フレームワークとソフトウェア デリバリー シールドをご覧ください。ソフトウェア デリバリー シールドは、ソフトウェアの開発、供給、CI / CD、ランタイムのライフサイクル全体にわたってソフトウェアのサプライ チェーンのセキュリティを強化する Google Cloud のフルマネージドかつエンドツーエンドのソリューションです。入門用資料については、Cloud Build についてのこちらのチュートリアルや、Artifact Registry についてのこちらのチュートリアルをご覧ください。
- デベロッパー リレーションズ エンジニア Anthony Bushong