
GSP479

概要
Kubernetes クラスタを実行する際のセキュリティ上の重要事項のひとつとして、各 Pod 内で実行されているコンテナ イメージとその出所を把握できなければならないという点があります。コンテナの由来を明確にするためには、コンテナのソースを信頼できる出所までトレースできる必要があります。また、組織がアーティファクト(コンテナ)を作成する際に適切なプロセスに従う必要があります。
主な懸念事項を以下に示します。
-
安全な由来 - クラスタ内で実行されているすべてのコンテナ イメージが承認済みのソースからのものであることを、どのように確認するか
-
整合性と検証 - コンテナのビルドとデプロイごとにすべての必要な検証ステップが正常に完了していることを、どのように確認するか
-
完全性 - 由来が証明されてから実行されるまでの間にコンテナが変更されていないことを、どのように確認するか
イメージの出所が厳密に管理されていない場合、セキュリティの観点からは次のようなリスクが生じます。
- 悪意のある人物によってコンテナが侵害された場合に、ソース不明の別のコンテナを起動できるクラスタ権限が取得されてしまう可能性があります。
- 意図的かどうかにかかわらず、Pod の作成権限を持つ正規のユーザーが、望ましくないコンテナをクラスタ内で直接実行する可能性があります。
- 意図的かどうかにかかわらず、正規のユーザーが、望ましくないコードが追加された実行可能なコンテナを使って Docker イメージタグを上書きする可能性があります。この場合、そのコンテナは Kubernetes によって Deployment の一部として自動的に pull およびデプロイされます。
こうした懸念にシステム オペレーターが対処できるように、Google Cloud には Binary Authorization と呼ばれる機能が用意されています。GKE と連携して機能するこの Google Cloud のマネージド サービスは、デプロイ時のセキュリティ管理を強化して、信頼されたコンテナ イメージのみがデプロイされるようにします。Binary Authorization を使用すると、コンテナ レジストリを許可リストに登録したり、イメージへの信頼できる機関による署名を必須にしたり、さらにそれらのポリシーを一元的に適用したりできます。ポリシーの適用により、承認されたイメージまたは適切であると確認されたイメージのみがビルドとリリースのプロセスに組み込まれるため、コンテナの環境をより厳密に管理できます。
このラボでは、Binary Authorization 機能が有効な Kubernetes Engine クラスタをデプロイして、承認済みのコンテナ レジストリを許可リストに登録する方法や、署名付きのコンテナを作成して実行するプロセスについて説明します。
このラボは、GKE での Binary Authorization に関する理解を深めていただくために GKE Helmsman のエンジニアによって作成されました。Google Cloud はアセットへの協力を歓迎しています。
アーキテクチャ
Binary Authorization API と Container Analysis API は、オープンソース プロジェクトの Grafeas と Kritis に基づいています。
- Grafeas は、コンテナ イメージ、仮想マシン(VM)イメージ、JAR ファイル、スクリプトなどのソフトウェア リソースに関するメタデータを管理するための API 仕様を定義しています。Grafeas を使用すると、プロジェクトのコンポーネントに関する情報を定義したり集約したりできます。
- Kritis は、一元的に管理されているポリシーに準拠していないアーティファクト(コンテナ イメージ)のデプロイを防止するための API を定義しています。必要な証明書があるかどうかを確認することもできます。
たとえば次のような、シンプルなコンテナ デプロイ パイプラインがあったとします。

この場合、コンテナは少なくとも次の 4 つのステップを通過します。
- コンテナを作成するためのソースコードがソース管理に保存されます。
- ソース管理に変更が commit されると、コンテナがビルドされてテストされます。
- ビルドとテストのステップが完了すると、コンテナ イメージのアーティファクトが中央のコンテナ レジストリに配置されて、デプロイできるようになります。
- そのコンテナ バージョンのデプロイのリクエストが Kubernetes API に送信されると、コンテナ ランタイムがそのコンテナ イメージをコンテナ レジストリから pull して Pod として実行します。
コンテナ ビルド パイプラインでは、各ステップが正常に完了したことを示す(「証明」する)追加のプロセスを挿入することが可能です。たとえば、単体テスト、ソース管理の分析の確認、ライセンスの確認、脆弱性分析などが実行されたことを確認できます。各ステップに、そのステップが完了したことを示す署名を行う権限、すなわち「証明書の認証局」としての役割を割り当てることもできます。「証明書の認証局」とは、正しい PGP 鍵とその「証明書」を Container Analysis API に登録する権限を持つ、人物またはシステムです。
ステップごとに異なる PGP 鍵を使用することで、各証明ステップをそれぞれ異なる人物、システム、またはパイプラインのビルドステップが実行できるようになります。(a) 各 PGP 鍵は、Container Analysis API に保存されている「証明書のメモ」に関連付けられています。ビルドステップによってイメージへの「署名」が行われると、そのイメージに関する JSON メタデータのスニペットに PGP による署名が行われて、その署名付きのスニペットが Container Analysis API に「メモの記録」として送信されます。

(b) コンテナ イメージがビルドされて必要な証明書が一元的に保存されると、ポリシー決定プロセスの一部として証明書のクエリを実行できるようになります。この場合、Kubernetes アドミッション コントローラが Pod の create
または update
の API リクエストを受け取ると次の処理が行われます。
- ポリシー決定のための Webhook が Binary Authorization API に送信されます。
- Binary Authorization ポリシーが参照されます。
- 必要に応じて Container Analysis API のクエリも行われ、必要な証明書があるかどうかが確認されます。
- コンテナ イメージがポリシーに準拠している場合は実行が許可されます。
- コンテナ イメージがポリシーの要件を満たしていない場合は API クライアントにエラーが返されます。エラーには、実行が許可されなかった理由を説明するメッセージが含まれています。

設定と要件
[ラボを開始] ボタンをクリックする前に
こちらの説明をお読みください。ラボには時間制限があり、一時停止することはできません。タイマーは、Google Cloud のリソースを利用できる時間を示しており、[ラボを開始] をクリックするとスタートします。
このハンズオンラボでは、シミュレーションやデモ環境ではなく実際のクラウド環境を使って、ラボのアクティビティを行います。そのため、ラボの受講中に Google Cloud にログインおよびアクセスするための、新しい一時的な認証情報が提供されます。
このラボを完了するためには、下記が必要です。
- 標準的なインターネット ブラウザ(Chrome を推奨)
注: このラボの実行には、シークレット モード(推奨)またはシークレット ブラウジング ウィンドウを使用してください。これにより、個人アカウントと受講者アカウント間の競合を防ぎ、個人アカウントに追加料金が発生しないようにすることができます。
- ラボを完了するための時間(開始後は一時停止できません)
注: このラボでは、受講者アカウントのみを使用してください。別の Google Cloud アカウントを使用すると、そのアカウントに料金が発生する可能性があります。
ラボを開始して Google Cloud コンソールにログインする方法
-
[ラボを開始] ボタンをクリックします。ラボの料金をお支払いいただく必要がある場合は、表示されるダイアログでお支払い方法を選択してください。
左側の [ラボの詳細] ペインには、以下が表示されます。
- [Google Cloud コンソールを開く] ボタン
- 残り時間
- このラボで使用する必要がある一時的な認証情報
- このラボを行うために必要なその他の情報(ある場合)
-
[Google Cloud コンソールを開く] をクリックします(Chrome ブラウザを使用している場合は、右クリックして [シークレット ウィンドウで開く] を選択します)。
ラボでリソースがスピンアップし、別のタブで [ログイン] ページが表示されます。
ヒント: タブをそれぞれ別のウィンドウで開き、並べて表示しておきましょう。
注: [アカウントの選択] ダイアログが表示されたら、[別のアカウントを使用] をクリックします。
-
必要に応じて、下のユーザー名をコピーして、[ログイン] ダイアログに貼り付けます。
{{{user_0.username | "Username"}}}
[ラボの詳細] ペインでもユーザー名を確認できます。
-
[次へ] をクリックします。
-
以下のパスワードをコピーして、[ようこそ] ダイアログに貼り付けます。
{{{user_0.password | "Password"}}}
[ラボの詳細] ペインでもパスワードを確認できます。
-
[次へ] をクリックします。
重要: ラボで提供された認証情報を使用する必要があります。Google Cloud アカウントの認証情報は使用しないでください。
注: このラボでご自身の Google Cloud アカウントを使用すると、追加料金が発生する場合があります。
-
その後次のように進みます。
- 利用規約に同意してください。
- 一時的なアカウントなので、復元オプションや 2 要素認証プロセスは設定しないでください。
- 無料トライアルには登録しないでください。
その後、このタブで Google Cloud コンソールが開きます。
注: Google Cloud のプロダクトやサービスにアクセスするには、ナビゲーション メニューをクリックするか、[検索] フィールドにサービス名またはプロダクト名を入力します。
Cloud Shell をアクティブにする
Cloud Shell は、開発ツールと一緒に読み込まれる仮想マシンです。5 GB の永続ホーム ディレクトリが用意されており、Google Cloud で稼働します。Cloud Shell を使用すると、コマンドラインで Google Cloud リソースにアクセスできます。
-
Google Cloud コンソールの上部にある「Cloud Shell をアクティブにする」アイコン
をクリックします。
-
ウィンドウで次の操作を行います。
- Cloud Shell 情報ウィンドウで操作を進めます。
- Cloud Shell が認証情報を使用して Google Cloud API を呼び出すことを承認します。
接続した時点で認証が完了しており、プロジェクトに各自の Project_ID、 が設定されます。出力には、このセッションの PROJECT_ID を宣言する次の行が含まれています。
Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}
gcloud
は Google Cloud のコマンドライン ツールです。このツールは、Cloud Shell にプリインストールされており、タブ補完がサポートされています。
- (省略可)次のコマンドを使用すると、有効なアカウント名を一覧表示できます。
gcloud auth list
- [承認] をクリックします。
出力:
ACTIVE: *
ACCOUNT: {{{user_0.username | "ACCOUNT"}}}
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- (省略可)次のコマンドを使用すると、プロジェクト ID を一覧表示できます。
gcloud config list project
出力:
[core]
project = {{{project_0.project_id | "PROJECT_ID"}}}
注: Google Cloud における gcloud
ドキュメントの全文については、gcloud CLI の概要ガイドをご覧ください。
タスク 1. リソースをコピーする
- 次のコマンドを実行して、このラボに必要なリソースをコピーします。
gsutil -m cp -r gs://spls/gke-binary-auth/* .
- このデモ用のディレクトリに移動します。
cd gke-binary-auth-demo
リージョンとゾーンを設定する
一部の Compute Engine リソースは、リージョン内やゾーン内に存在します。リージョンとは、リソースを実行できる特定の地理的なロケーションです。1 つのリージョンには 1 つ以上のゾーンがあります。
注: リージョンおよびゾーンの詳細と一覧については、リージョンとゾーンのドキュメントをご覧ください。
次のコマンドを実行して、ラボのリージョンとゾーンを設定します(最適なリージョンとゾーンを使用できます)。
gcloud config set compute/region {{{ project_0.default_region | REGION }}}
gcloud config set compute/zone {{{ project_0.default_zone | ZONE }}}
ファイルへのアクセス許可を更新する
- 次に、このラボに必要なリソースによる一部のファイルの読み取り、書き込み、実行を可能にします。
chmod +x create.sh
chmod +x delete.sh
chmod 777 validate.sh
タスク 2. デフォルトのクラスタ バージョンを設定する
-
create.sh
の GKE_VERSION 変数を defaultClusterVersion
に変更します。
sed -i 's/validMasterVersions\[0\]/defaultClusterVersion/g' ./create.sh
注: デフォルトのクラスタ バージョンは、このラボの他の依存関係に対応するものになります。
タスク 3. デプロイ手順を実行する
注: 以下の手順は、デプロイに Cloud Shell を使用する場合と使用しない場合の両方に対応しています。
- クラスタをデプロイするには次のコマンドを実行します。テキスト
my-cluster-1
は、作成したいクラスタの名前に自由に置き換えてかまいません。
./create.sh -c my-cluster-1
この create
スクリプトが完了すると、次のようなメッセージが出力されます。
kubeconfig entry generated for my-cluster-1.
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
my-cluster-1 {{{project_0.default_zone | Zone}}} 1.14.8-gke.17 104.154.181.211 n1-standard-1 1.14.8-gke.17 2 RUNNING
Fetching cluster endpoint and auth data.
kubeconfig entry generated for my-cluster-1.
このスクリプトによって行われる処理は次のとおりです。
- プロジェクトで必要な API を有効にします。具体的には、
container
、containerregistry
、containeranalysis
、binaryauthorization
が有効になります。
- デフォルトのゾーン、VPC、ネットワークを使用して新しい Kubernetes Engine クラスタを作成します。
- クラスタの認証情報を取得して
kubectl
を使用できるようにします。
警告は無視してかまいません。
タスク 4. 検証を行う
- 次のスクリプトを使用して、デモが正しくデプロイされていることを確認します。
./validate.sh -c my-cluster-1
このスクリプトが失敗すると次のような出力が返されます。
Validation Failed: the BinAuthZ policy was NOT available
および / または
Validation Failed: the Container Analysis API was NOT available
このスクリプトが成功すると次のような出力が返されます。
Validation Passed: the BinAuthZ policy was available
Validation Passed: the Container Analysis API was available
完了したタスクをテストする
[進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization の有効な Kubernetes クラスタが正常に作成されている場合は、評価スコアが表示されます。
Binary Authorization が有効な Kubernetes クラスタを作成する
タスク 5. Binary Authorization を使用する
Binary Authorization ポリシーを管理する
Binary Authorization のポリシー構成 UI にアクセスするには、次の手順に沿って操作します。
- Google Cloud コンソールで、[セキュリティ] > [Binary Authorization] に移動します。

- [ポリシーの編集] をクリックします。

注: gcloud
で Binary Authorization のポリシー構成にアクセスする手順は次のとおりです。
gcloud beta container binauthz policy export > policy.yaml
を実行します。
policy.yaml
を必要に応じて編集します。
gcloud beta container binauthz policy import policy.yaml
を実行します。
これから編集するポリシーは「デフォルト」のポリシーです。デフォルトのポリシーは、クラスタ固有のポリシーを構成しない限り、Google Cloud プロジェクトのすべての GKE クラスタに適用されます。
おすすめの方法は、クラスタごとに固有のポリシーを作成してオペレーションが成功するように構成(必要に応じてレジストリを許可リストに登録するなど)し、デフォルトのプロジェクト レベルのポリシーを、すべてのイメージを禁止するように設定することです。その場合、このプロジェクトで新しいクラスタを作成するたびにそのクラスタに固有のポリシーを構成する必要があります。
- [ポリシーを編集] をクリックすると、次の画面が表示されます。

デフォルトのポリシールールは [すべてのイメージを許可
] です。この場合、クラスタで Binary Authorization が有効になっていない場合と同様に動作します。
デフォルトのルールを [すべてのイメージを禁止
] に変更すると、除外されたレジストリ イメージのパスに一致しないイメージがブロックされます。[次のすべての認証によって承認されたイメージのみを許可
] に変更すると、必要な証明書がないイメージがブロックされます。
次に、このポリシーを次のように編集します。
-
[デフォルトのルール] を [すべてのイメージを禁止
] に変更します。
-
[GKE と Anthos のデプロイ向けの追加設定] で、[固有のルールを作成] をクリックします。
-
プルダウンから [GKE クラスタ] を選択し、[変更] をクリックします。
-
[GKE クラスタ固有のルール] で、[固有のルールを追加] をクリックします。
-
[GKE クラスタ固有のルールの追加] フィールドに、使用しているロケーションとクラスタ名を location.clustername
という形式で入力します(たとえば、ゾーン名が でクラスタ名が my-cluster-1
の場合は.my-cluster-1)。
-
クラスタのデフォルト ルールとして [すべてのイメージを許可
] を選択します。
-
[追加] をクリックします。

- [ポリシーを保存] をクリックします。
完了したタスクをテストする
[進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization ポリシーが正常に更新されて、プロジェクト レベルの「すべてのイメージを禁止」ルールとクラスタレベルの「すべてのイメージを許可」ルールが追加されている場合は、評価スコアが表示されます。
Binary Authorization ポリシーを更新してプロジェクト レベルの「すべてのイメージを禁止」ルールとクラスタレベルの「すべてのイメージを許可」ルールを追加する
タスク 6. 限定公開の GCR イメージを作成する
-
実際の構成をシミュレートするために、プロジェクト内に限定公開の Google Container Registry(GCR)コンテナ イメージを作成します。
-
nginx
プロジェクトから nginx
コンテナを pull して、変更しないまま現在の GCR リポジトリに push します。
-
Cloud Shell で、latest
の nginx
コンテナを pull します。
docker pull nginx:latest
- プロジェクトに対して Docker を認証します。
gcloud auth configure-docker
Do you want to continue (Y/n)?
というプロンプトが表示されたら、「Y
」と入力します。
- PROJECT_ID シェル変数を設定します。
PROJECT_ID="$(gcloud config get-value project)"
- pull したイメージにタグを付けて現在のプロジェクトの GCR に push します。
docker tag nginx "gcr.io/${PROJECT_ID}/nginx:latest"
docker push "gcr.io/${PROJECT_ID}/nginx:latest"
- 現在の GCR リポジトリにある「限定公開」の nginx イメージを表示します。
gcloud container images list-tags "gcr.io/${PROJECT_ID}/nginx"
タスク 7. すべてのイメージを禁止する
ポリシーによるイメージの禁止が想定どおりに機能することを実証するために、まず、クラスタ固有の allow
ルールが適用されており、すべてのコンテナの実行が許可されることを確認します。
- そのためには、
nginx
Pod を 1 つ起動します。
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "gcr.io/${PROJECT_ID}/nginx:latest"
ports:
- containerPort: 80
EOF
「pod/nginx created
」というメッセージが表示されます。
- Pod を一覧表示します。
kubectl get pods
出力:
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 1m
失敗した場合は、クラスタ固有のルールのリージョンと名前を再確認してやり直します。
- 完了したら、この Pod を削除します。
kubectl delete pod nginx
- 次に、望ましくないイメージが Binary Authorization ポリシーによってブロックされてクラスタ内で実行されないことを確認します。
[Binary Authorization] ページで [ポリシーを編集] をクリックします。
-
GKE クラスタ固有のルールの右にあるその他アイコン(3 つの点)、[編集] の順にクリックします。
-
次に、[すべてのイメージを禁止
] を選択し、[送信] をクリックします。
ポリシーが次のようになります。
![[すべてのイメージを禁止] オプションを選択した状態の「us-central1-a.mycluster-1 に関する GKE クラスタ固有のルールの編集」ダイアログ ボックス](https://cdn.qwiklabs.com/B1Lz5UwF9pTxbQtGqwnU8lmWMobP8cQfM9W4UtQJNK4%3D)
- 最後に、[ポリシーを保存] をクリックしてこれらの変更を適用します。
注: ポリシーが有効になるまで少なくとも 30 秒待ってから次に進んでください。
完了したタスクをテストする
[進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization ポリシーが正常に更新されて、クラスタレベルのルールが [すべてのイメージを禁止] に変更されている場合は、評価スコアが表示されます。
クラスタ固有のルールを [すべてのイメージを禁止] に変更する
- 次に、先ほどと同じコマンドを実行して静的な
nginx
Pod を作成します。
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "gcr.io/${PROJECT_ID}/nginx:latest"
ports:
- containerPort: 80
EOF
今回は、ポリシーが原因でこの Pod を実行できなかったという内容のメッセージが API サーバーから返されます。
Error from server (VIOLATES_POLICY): error when creating "STDIN": admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/qwiklabs-gcp-00-ce851250686b/nginx:latest denied by Binary Authorization cluster admission rule for {{{project_0.default_zone | Zone}}}.my-cluster-1. Denied by always_deny admission rule
Binary Authorization ポリシーによってイメージがブロックされた日時を確認するには、オペレーション スイートの GKE 監査ログに移動して、このアクティビティに関連するエラー メッセージでフィルタします。
- Google Cloud コンソールで、ナビゲーション メニュー > [ロギング] > [ログ エクスプローラ] に移動します。
-
クエリビルダー ボックスに次のコードを入力します。
resource.type="k8s_cluster" protoPayload.response.reason="VIOLATES_POLICY"

- [クエリを実行] をクリックします。
-
nginx
Pod の実行のブロックに対応するエラーが表示されます。
完了したタスクをテストする
[進行状況を確認] をクリックして、実行したタスクを確認します。クラスタ アドミッション ルールの確認が正常に行われた場合は、評価スコアが表示されます。
Nginx Pod を作成して、すべてのイメージを禁止する(作成を拒否する)クラスタ アドミッション ルールが適用されていることを確認する
タスク 8. 許可リストに登録されているコンテナ レジストリ以外のイメージを禁止する
-
この nginx コンテナのみに実行を許可したい場合はどうすればよいでしょうか。最も簡単な方法は、このコンテナのソースであるレジストリを許可リストに登録することです。
-
次のコマンドの出力をイメージパスとして使用します。
echo "gcr.io/${PROJECT_ID}/nginx*"
-
イメージパスの出力をバッファにコピーします。
-
ナビゲーション メニュー > [セキュリティ] > [Binary Authorization] に移動します。
-
Binary Authorization ポリシーを編集します。[カスタム除外ルール] イメージパスが表示されてから、[イメージ パターンを追加] をクリックします。
-
先ほどコピーしたイメージパスを貼り付けます。次の図は、パスの例を示しています。

- [ポリシーを保存] をクリックして、次のコマンドを実行します。
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "gcr.io/${PROJECT_ID}/nginx:latest"
ports:
- containerPort: 80
EOF
今度はこの Pod を起動できるはずです。これにより、レジストリの許可リストが正常に機能していることがわかります。
- クリーンアップと次のステップの準備のために次のコマンドを実行します。
kubectl delete pod nginx
完了したタスクをテストする
[進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization ポリシーが正常に更新されて、コンテナ レジストリが許可リストに登録されている場合は、評価スコアが表示されます。
Binary Authorization ポリシーを更新して、許可リストに登録されているコンテナ レジストリ(現在のプロジェクトのコンテナ レジストリ)以外のイメージを禁止する
タスク 9. 証明書を必須にする
コンテナ イメージ レジストリを許可リストに登録することは、望ましくないコンテナ イメージがクラスタ内で実行されるのを防ぐための最初のステップとして効果的ですが、コンテナが正しくビルドされていることを確認するためにできることは他にもあります。
たとえば、特定のコンテナ イメージのデプロイが承認されているかどうかを暗号によって確認できます。これには「証明書の認証局」を使用します。証明書の認証局は、特定のステップが完了したことを証明するために、コンテナ イメージの SHA256 ハッシュを記述するメタデータのスニペットに PGP 鍵で署名して、それを一元的なメタデータ リポジトリ(Container Analysis API)に送信します。
その後、コンテナ イメージの実行が許可されているかどうかをアドミッション コントローラが確認します。これは、イメージに証明書が存在することを要件とする Binary Authorization ポリシーを調べることによって行われます。このとき、完了したステップを示す署名付きメタデータ スニペットが Container Analysis API に保持されているかどうかが確認されます。この情報により、アドミッション コントローラは、その Pod の実行を許可すべきかどうかを判断します。
次に、コンテナ イメージに手動の証明書を適用します。人間の「証明書の認証局」として、コンテナ イメージへの署名に必要なすべてのステップを実行し、クラスタ内で実行されるイメージに証明書が存在することを要求するポリシーを作成して、署名したイメージが Pod で正常に実行されることを確認します。
必要な変数を設定する
- 認証者の詳細(名前とメールアドレス)を設定します。
ATTESTOR="manually-verified" # スペースは使用できません
ATTESTOR_NAME="Manual Attestor"
ATTESTOR_EMAIL="$(gcloud config get-value core/account)" # これにより現在のユーザーとメールアドレスが使用されます
- 証明書の認証局の Container Analysis メモの ID と説明を設定します。
NOTE_ID="Human-Attestor-Note" # スペースは使用できません
NOTE_DESC="Human Attestation Note Demo"
- ペイロードとリクエストを作成するためのファイルの名前を設定します。
NOTE_PAYLOAD_PATH="note_payload.json"
IAM_REQUEST_JSON="iam_request.json"
証明書のメモを作成する
まず、証明書の認証局を Container Analysis メモとして Container Analysis API に登録します。そのためには、ATTESTATION
メモを作成して Container Analysis API に送信します。
-
ATTESTATION
メモのペイロードを作成します。
cat > ${NOTE_PAYLOAD_PATH} << EOF
{
"name": "projects/${PROJECT_ID}/notes/${NOTE_ID}",
"attestation_authority": {
"hint": {
"human_readable_name": "${NOTE_DESC}"
}
}
}
EOF
-
ATTESTATION
メモを Container Analysis API に送信します。
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @${NOTE_PAYLOAD_PATH} \
"https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
作成されたメモは、前のコマンドの出力に表示されますが、次のコマンドでも表示できます。
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
PGP 署名鍵を作成する
この証明書の認証局はイメージ メタデータへの暗号署名に PGP 鍵を使用するため、新しい PGP 鍵を作成して公開 PGP 鍵をエクスポートします。
注: このエラー メッセージはこのアクティビティに関連しています。この演習の PGP 鍵はパスワードで保護されていません。本番環境のシステムでは、秘密 PGP 鍵を適切に保護する必要があります。
- 別のシェル変数を設定します。
PGP_PUB_KEY="generated-key.pgp"
- PGP 鍵を作成します。
sudo apt-get install rng-tools
sudo rngd -r /dev/urandom
gpg --quick-generate-key --yes ${ATTESTOR_EMAIL}
-
Enter キーを押して空のパスフレーズを使用し、表示される警告を承諾します。
-
公開 PGP 鍵を抽出します。
gpg --armor --export "${ATTESTOR_EMAIL}" > ${PGP_PUB_KEY}
Binary Authorization API で認証者を登録する
次に、Binary Authorization API で「認証者」を作成して公開 PGP 鍵を追加します。
- Binary Authorization API で認証者を作成します。
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors create "${ATTESTOR}" \
--attestation-authority-note="${NOTE_ID}" \
--attestation-authority-note-project="${PROJECT_ID}"
- 認証者に PGP 鍵を追加します。
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors public-keys add \
--attestor="${ATTESTOR}" \
--pgp-public-key-file="${PGP_PUB_KEY}"
- 新たに作成された認証者を表示します。
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors list
出力は次のようになります。
NAME: manually-verified
NOTE: projects//notes/Human-Attestor-Note
NUM_PUBLIC_KEYS: 1
タスク 10. コンテナ イメージに「署名」する
これまでのステップと次以降のステップを実行するのは 1 回だけですが、このステップは新しいコンテナ イメージを作成するたびに実行する必要があります。
nginx:latest
の nginx
イメージは、すでにビルドされて使用できる状態になっています。このイメージに対して、独自のプロセスによってビルドされた独自のイメージの場合と同様に、手動の証明書を適用します。これにより、イメージをビルドする手間を省くことができます。
- シェル変数をいくつか設定します。
GENERATED_PAYLOAD="generated_payload.json"
GENERATED_SIGNATURE="generated_signature.pgp"
- PGP フィンガープリントを取得します。
PGP_FINGERPRINT="$(gpg --list-keys ${ATTESTOR_EMAIL} | head -2 | tail -1 | awk '{print $1}')"
- このコンテナ イメージの SHA256 ダイジェストを取得します。
IMAGE_PATH="gcr.io/${PROJECT_ID}/nginx"
IMAGE_DIGEST="$(gcloud container images list-tags --format='get(digest)' $IMAGE_PATH | head -1)"
- JSON 形式の署名ペイロードを作成します。
gcloud beta container binauthz create-signature-payload \
--artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" > ${GENERATED_PAYLOAD}
- 生成された署名ペイロードを表示します。
cat "${GENERATED_PAYLOAD}"
- PGP 鍵を使用してペイロードに「署名」します。
gpg --local-user "${ATTESTOR_EMAIL}" \
--armor \
--output ${GENERATED_SIGNATURE} \
--sign ${GENERATED_PAYLOAD}
- 生成された署名(PGP メッセージ)を表示します。
cat "${GENERATED_SIGNATURE}"
- 証明書を作成します。
gcloud beta container binauthz attestations create \
--artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" \
--attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}" \
--signature-file=${GENERATED_SIGNATURE} \
--public-key-id="${PGP_FINGERPRINT}"
- 新たに作成された証明書を表示します。
gcloud beta container binauthz attestations list \
--attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}"
タスク 11. 証明書の必須化を有効にしてイメージを実行する
次に、Binary Authorization ポリシーを変更して、許可リストのパターンに一致しないすべてのイメージで証明書の存在を必須にします。
- 証明書を要求するようにポリシーを変更するには、まず、次のコマンドを実行して、証明書の認証局のフルパスと名前をコピーします。
echo "projects/${PROJECT_ID}/attestors/${ATTESTOR}" # コピー / 貼り付けバッファにこの出力をコピーします
- 次に、Binary Authorization ポリシーを編集して、GKE クラスタ固有のルールを
編集
します。
現在のクラスタ名の横にあるその他アイコン(3 つの点)をクリックして、クラスタ固有ルールの [編集] を選択します。
- ポップアップ ウィンドウの [
すべてのイメージを禁止
] の代わりに、[証明書を要求: 次の認証者によって検証されたイメージのみを許可します
] を選択します。
![[すべてのイメージを禁止] オプションを選択した状態のポリシーの編集ページ](https://cdn.qwiklabs.com/HXkk8WbGxIy16NT5N3n6%2BeDpiKBY8SrL6BmsIgBBGMQ%3D)
- 次に、[
認証者の追加
] をクリックし、[認証者リソース ID により追加
] をクリックします。コピー / 貼り付けバッファの内容を projects/${PROJECT_ID}/attestors/${ATTESTOR}
という形式で入力し、[認証者の追加]、[送信]、[ポリシーを保存] の順にクリックします。

デフォルトのポリシーは [すべてのイメージを禁止
] のままですが、クラスタ固有のルールでは証明書が要求されています。
- 次に、前のステップで署名したイメージの最新の SHA256 ダイジェストを取得します。
IMAGE_PATH="gcr.io/${PROJECT_ID}/nginx"
IMAGE_DIGEST="$(gcloud container images list-tags --format='get(digest)' $IMAGE_PATH | head -1)"
- Binary Authorization ポリシーを更新してから 30 秒以上経ったら Pod を実行して、正常に実行されることを確認します。
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "${IMAGE_PATH}@${IMAGE_DIGEST}"
ports:
- containerPort: 80
EOF
お疲れさまでした。コンテナ イメージに手動の証明書を適用し、GKE クラスタ内でそのイメージに対してポリシーを適用できました。
完了したタスクをテストする
[進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization ポリシーが正常に更新されて、認証者によって承認されているイメージのみを許可するようにクラスタ固有のルールが変更されている場合は、評価スコアが表示されます。
Binary Authorization ポリシーを更新して、認証者によって承認されているイメージのみを許可するようにクラスタ固有のルールを変更する
タスク 12. 緊急事態に対処する
ユーザー側から見ると、Binary Authorization ポリシーがイメージを誤ってブロックする可能性や、アドミッション コントローラ Webhook の正常な機能を妨げるその他の問題が発生する可能性があります。
こうした「緊急事態」に対処するために、「ブレークグラス」機能が用意されています。これにより、特殊なアノテーションを使用して、ポリシーの適用をスキップして Pod を実行するようにアドミッション コントローラに通知できます。
注: このような状況が発生した場合は、セキュリティ チームに通知する必要があります。悪意のあるユーザーに Pod を作成する権限を取得されて、この機能を悪用される可能性があるからです。ただし、そのような場合、アクティビティの発生から数秒で対応を開始できます。ログは Stackdriver で確認できます。
- 「ブレークグラス」アノテーションを使用して未署名の
nginx
コンテナを実行するには、次のコマンドを使用します。
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-alpha
annotations:
alpha.image-policy.k8s.io/break-glass: "true"
spec:
containers:
- name: nginx
image: "nginx:latest"
ports:
- containerPort: 80
EOF
-
Google Cloud コンソールで、ナビゲーション メニュー > [ロギング] > [ログ エクスプローラ] ページに移動します。
-
クエリビルダー ボックスに次のコードを入力し、[クエリを実行] をクリックします。
resource.type="k8s_cluster" protoPayload.request.metadata.annotations."alpha.image-policy.k8s.io/break-glass"="true"
-
前述のアノテーションによって Pod が許可された場合は、イベントが表示されます。このフィルタからシンク
を作成して、このフィルタに一致するログを外部の宛先に送信できます。

注: ログが表示されるまで、少なくとも 5~10 分かかります。
タスク 13. クラスタを破棄する
このラボで作成したすべてのリソースは Qwiklabs によって削除されますが、実際の環境をクリーンアップする方法を学習しておきましょう。
- 次のスクリプトで Kubernetes Engine クラスタを破棄します。
./delete.sh -c my-cluster-1
このラボの始めに独自のクラスタ名を指定した場合はその名前を使用してください。この例で使用されている名前は my-cluster-1
です。
出力の最後の行が次のようになります。
Deleting cluster
注: クラスタの削除コマンドは非同期で実行され、完了までにしばらくかかります。進捗状況を追跡するには、Cloud コンソール UI または gcloud container clusters list
コマンドを使用します。クラスタが削除されるまで待ちます。
完了したタスクをテストする
[進行状況を確認] をクリックして、実行したタスクを確認します。クラスタが正常に削除された場合は、評価スコアが表示されます。
クラスタを破棄(削除)する
以下のコマンドで残りのリソースを削除します。
- GCR に push したコンテナ イメージを削除します。
gcloud container images delete "${IMAGE_PATH}@${IMAGE_DIGEST}" --force-delete-tags
-
[Do you want to continue (Y/n)
] というメッセージが表示されたら、「Y」
と入力します。
-
認証者を削除します。
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors delete "${ATTESTOR}"
- Container Analysis メモを削除します。
curl -X DELETE \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
独自の環境でのトラブルシューティング
- Binary Authorization ポリシーを更新してすぐに新しい Pod やコンテナを起動しようとすると、ポリシーがまだ有効になっていないことがあります。ポリシーの変更が有効になるまでには 30 秒以上かかる場合があります。再試行するには、
kubectl delete <podname>
を使用して Pod を削除してから Pod 作成コマンドを再送信します。
- クラスタのステータスを確認するには
gcloud container clusters list
コマンドを実行します。
- 追加機能を有効にした場合は(
--enable-network-policy
、--accelerator
、--enable-tpu
、--enable-metadata-concealment
など)、Binary Authorization ポリシーの許可リストにレジストリをさらに追加しないと Pod を実行できない可能性があります。kubectl describe pod <podname>
を使用してイメージ仕様でレジストリパスを確認し、gcr.io/example-registry/*
という形式で許可リストに追加してポリシーを保存します。
- 割り当てに関するエラーが表示された場合は、プロジェクトの割り当てを増やしてください。リソースの割り当ての詳細については、リソースの割り当てに関するドキュメントをご覧ください。
関連資料
- Google Cloud の割り当て
- Google Cloud への登録
- Google Cloud Shell
- GKE の Binary Authorization
- Container Analysis のメモ
- Kubernetes アドミッション コントローラ
- リリース ステージ
お疲れさまでした
このラボでは、Binary Authorization を使用して Kubernetes Engine クラスタをデプロイし、環境を保護する方法について学習しました。
マニュアルの最終更新日: 2025 年 2 月 27 日
ラボの最終テスト日: 2025 年 2 月 27 日
Copyright 2024 Google LLC. 本ソフトウェアは「現状有姿」で提供されており、いかなる使用および目的に関しても保証および表明は伴いません。本ソフトウェアのご利用には、Google との契約が適用されます。