arrow_back

Google Kubernetes Engine のセキュリティ: Binary Authorization

参加 ログイン
Test and share your knowledge with our community!
done
Get access to over 700 hands-on labs, skill badges, and courses

Google Kubernetes Engine のセキュリティ: Binary Authorization

Lab 1時間 30分 universal_currency_alt クレジット: 5 show_chart 中級
Test and share your knowledge with our community!
done
Get access to over 700 hands-on labs, skill badges, and courses

GKE-Engine.png

GSP479

Google Cloud セルフペース ラボ

概要

Kubernetes クラスタ実行時の主なセキュリティ上の重要事項のひとつとして、各 Pod 内で実行されているコンテナ イメージと、その出所を把握できなければならないという点があります。コンテナの由来を明確化するためには、コンテナのソースを信頼できる出所までトレースできるようにし、また組織がアーティファクト(コンテナ)作成時に望ましいプロセスに従う必要があります。

主な懸念事項を以下に示します。

  • 安全な由来 - クラスタ内で実行されているすべてのコンテナ イメージが承認済みのソースからのものであることを、どのように確認するか
  • 整合性と検証 - コンテナのビルドとデプロイごとにすべての必要な検証ステップが正常に完了していることを、どのように確認するか
  • 完全性 - 由来が証明されてから実行されるまでの間にコンテナが変更されていないことを、どのように確認するか

イメージの出所の管理が厳密に適用されていない場合、セキュリティの観点から見て次のようなリスクが生じます。

  • 悪意のある人物によってコンテナが侵害された場合に、ソース不明の別のコンテナを起動できるクラスタ権限が取得されてしまう可能性があります。
  • Pod を作成する権限を持つ正規のユーザーが、意図的かどうかにかかわらず、望ましくないコンテナをクラスタ内で直接実行する可能性があります。
  • 正規のユーザーが、意図的かどうかにかかわらず、望ましくないコードが知らない間に追加された実行可能なコンテナを使って Docker イメージタグを上書きする可能性があります。この場合、そのコンテナは、Deployment の一部として自動的に pull されてデプロイされます。

こうした懸念にシステム オペレーターが対処できるように、Google Cloud には Binary Authorization と呼ばれる機能が用意されています。Binary Authorization は Google Cloud のマネージド サービスで、GKE と緊密に連携してデプロイ時のセキュリティ管理を強化し、信頼されたコンテナ イメージのみがデプロイされるようにします。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 つのステップを通過します。

  1. コンテナを作成するためのソースコードがソース管理に保存されます。
  2. ソース管理に変更が commit されると、コンテナがビルドされてテストされます。
  3. ビルドとテストのステップが完了すると、コンテナ イメージのアーティファクトが中央のコンテナ レジストリに配置されて、デプロイできるようになります。
  4. そのコンテナ バージョンのデプロイのリクエストが 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 リクエストを受け取ると次の処理が行われます。

  1. ポリシー決定のための Webhook が Binary Authorization API に送信されます。
  2. Binary Authorization ポリシーが参照されます。
  3. 必要に応じて Container Analysis API のクエリも行われ、必要な証明書のオカレンスがあるかどうかが確認されます。
  4. コンテナ イメージがポリシーに準拠している場合は実行が許可されます。
  5. コンテナ イメージがポリシーの要件を満たしていない場合は API クライアントにエラーが返されます。エラーには、実行が阻止された理由を説明するメッセージが含まれています。

適用の図

設定

[ラボを開始] ボタンをクリックする前に

こちらの手順をお読みください。ラボの時間は記録されており、一時停止することはできません。[ラボを開始] をクリックするとスタートするタイマーは、Google Cloud のリソースを利用できる時間を示しています。

このハンズオンラボでは、シミュレーションやデモ環境ではなく、実際のクラウド環境を使ってご自身でラボのアクティビティを行うことができます。そのため、ラボの受講中に Google Cloud にログインおよびアクセスするための、新しい一時的な認証情報が提供されます。

このラボを完了するためには、下記が必要です。

  • 標準的なインターネット ブラウザ(Chrome を推奨)
注: このラボの実行には、シークレット モードまたはシークレット ブラウジング ウィンドウを使用してください。これにより、個人アカウントと受講者アカウント間の競合を防ぎ、個人アカウントに追加料金が発生することを防ぎます。
  • ラボを完了するために十分な時間を確保してください。ラボをいったん開始すると一時停止することはできません。
注: すでに個人の Google Cloud アカウントやプロジェクトをお持ちの場合でも、このラボでは使用しないでください。アカウントへの追加料金が発生する可能性があります。

ラボを開始して Google Cloud コンソールにログインする方法

  1. [ラボを開始] ボタンをクリックします。ラボの料金をお支払いいただく必要がある場合は、表示されるポップアップでお支払い方法を選択してください。 左側の [ラボの詳細] パネルには、以下が表示されます。

    • [Google コンソールを開く] ボタン
    • 残り時間
    • このラボで使用する必要がある一時的な認証情報
    • このラボを行うために必要なその他の情報(ある場合)
  2. [Google コンソールを開く] をクリックします。 ラボでリソースが起動し、別のタブで [ログイン] ページが表示されます。

    ヒント: タブをそれぞれ別のウィンドウで開き、並べて表示しておきましょう。

    注: [アカウントの選択] ダイアログが表示されたら、[別のアカウントを使用] をクリックします。
  3. 必要に応じて、[ラボの詳細] パネルから [ユーザー名] をコピーして [ログイン] ダイアログに貼り付けます。[次へ] をクリックします。

  4. [ラボの詳細] パネルから [パスワード] をコピーして [ようこそ] ダイアログに貼り付けます。[次へ] をクリックします。

    重要: 認証情報は左側のパネルに表示されたものを使用してください。Google Cloud Skills Boost の認証情報は使用しないでください。 注: このラボでご自身の Google Cloud アカウントを使用すると、追加料金が発生する場合があります。
  5. その後次のように進みます。

    • 利用規約に同意してください。
    • 一時的なアカウントなので、復元オプションや 2 要素認証プロセスは設定しないでください。
    • 無料トライアルには登録しないでください。

その後このタブで Cloud Console が開きます。

注: 左上にある [ナビゲーション メニュー] をクリックすると、Google Cloud のプロダクトやサービスのリストが含まれるメニューが表示されます。 ナビゲーション メニュー アイコン

Cloud Shell をアクティブにする

Cloud Shell は、開発ツールと一緒に読み込まれる仮想マシンです。5 GB の永続ホーム ディレクトリが用意されており、Google Cloud で稼働します。Cloud Shell を使用すると、コマンドラインで Google Cloud リソースにアクセスできます。

  1. Google Cloud コンソールの上部にある「Cloud Shell をアクティブにする」アイコン 「Cloud Shell をアクティブにする」アイコン をクリックします。

接続した時点で認証が完了しており、プロジェクトに各自の PROJECT_ID が設定されます。出力には、このセッションの PROJECT_ID を宣言する次の行が含まれています。

Your Cloud Platform project in this session is set to YOUR_PROJECT_ID

gcloud は Google Cloud のコマンドライン ツールです。このツールは、Cloud Shell にプリインストールされており、タブ補完がサポートされています。

  1. (省略可)次のコマンドを使用すると、有効なアカウント名を一覧表示できます。
gcloud auth list
  1. [承認] をクリックします。

  2. 出力は次のようになります。

出力:

ACTIVE: * ACCOUNT: student-01-xxxxxxxxxxxx@qwiklabs.net To set the active account, run: $ gcloud config set account `ACCOUNT`
  1. (省略可)次のコマンドを使用すると、プロジェクト ID を一覧表示できます。
gcloud config list project

出力:

[core] project = <project_ID>

出力例:

[core] project = qwiklabs-gcp-44776a13dea667a6 注: Google Cloud における gcloud ドキュメントの全文については、gcloud CLI の概要ガイドをご覧ください。

タスク 1. リソースのコピー

  1. 次のコマンドを実行して、このラボに必要なリソースをコピーします。
gsutil -m cp -r gs://spls/gke-binary-auth/* .
  1. このデモ用のディレクトリに移動します。
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.shGKE_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.

このスクリプトによって行われる処理は次のとおりです。

  1. プロジェクトで必要な API を有効にします。具体的には、containercontainerregistrycontaineranalysisbinaryauthorization が有効になります。
  2. デフォルトのゾーン、VPC、ネットワークを使用して新しい Kubernetes Engine クラスタを作成します。
  3. クラスタの認証情報を取得して 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 にアクセスするには、次の手順に沿って操作します。

  1. Google Cloud コンソールで、[セキュリティ] > [Binary Authorization] に移動します。

ナビゲーション メニューが開かれていて、Binary Authorization オプションがハイライト表示されている

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

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 クラスタに適用されます。

    おすすめの方法は、クラスタごとに固有のポリシーを作成してオペレーションが成功するように構成(必要に応じてレジストリを許可リストに登録するなど)し、デフォルトのプロジェクト レベルのポリシーを、すべてのイメージを禁止するように設定することです。その場合、このプロジェクトで新しいクラスタを作成するたびにそのクラスタに固有のポリシーを構成する必要があります。

    1. [ポリシーを編集] をクリックすると、次の画面が表示されます。[カスタム除外ルール] の横にある下矢印をクリックしてカスタム除外ルールを表示します。

    ポリシーの編集ページ

    デフォルトのポリシールールは [すべてのイメージを許可] です。この場合、クラスタで Binary Authorization が有効になっていない場合と同様に動作します。

    デフォルトのルールを [すべてのイメージを禁止] に変更すると、除外されたレジストリ イメージのパスに一致しないイメージがブロックされます。[次のすべての認証によって承認されたイメージのみを許可] に変更すると、必要な証明書がないイメージがブロックされます。

    次に、このポリシーを次のように編集します。

    1. [デフォルトのルール] を [すべてのイメージを禁止] に変更します。

    2. [GKE と Anthos のデプロイ向けの追加設定] で、[固有のルールを作成] をクリックします。

    3. プルダウンから [GKE クラスタ] を選択し、[変更] をクリックします。

    4. [GKE クラスタ固有のルール] で、[固有のルールを追加] をクリックします。

    5. [GKE クラスタ固有のルールの追加] フィールドに、使用しているロケーションとクラスタ名を location.clustername という形式で入力します(たとえば、ゾーン名が でクラスタ名が my-cluster-1 の場合は.my-cluster-1)。

    6. クラスタのデフォルト ルールとして [すべてのイメージを許可] を選択します。

    7. [追加] をクリックします。

    「GKE クラスタ固有のルールの追加」ダイアログ ボックス

    1. [ポリシーを保存] をクリックします。

    完了したタスクをテストする

    [進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization ポリシーが正常に更新されて、プロジェクト レベルの「すべてのイメージを禁止」ルールとクラスタレベルの「すべてのイメージを許可」ルールが追加されている場合は、評価スコアが表示されます。

    Binary Authorization ポリシーを更新してプロジェクト レベルの「すべてのイメージを禁止」ルールとクラスタレベルの「すべてのイメージを許可」ルールを追加する

    タスク 6. 限定公開の GCR イメージを作成する

    1. 実際の構成をシミュレートするために、限定公開の Google Container Registry(GCR)コンテナ イメージをプロジェクトで作成します。

    2. gcr.io/google-containers/nginx プロジェクトから nginx コンテナを pull して、変更しないまま現在の GCR リポジトリに push します。

    3. Cloud Shell で、latestnginx コンテナを pull します。

    docker pull gcr.io/google-containers/nginx:latest
    1. プロジェクトに対して Docker を認証します。
    gcloud auth configure-docker

    Do you want to continue (Y/n)? というプロンプトが表示されたら、「Y」と入力します。

    1. PROJECT_ID シェル変数を設定します。
    PROJECT_ID="$(gcloud config get-value project)"
    1. pull したイメージにタグを付けて現在のプロジェクトの GCR に push します。
    docker tag gcr.io/google-containers/nginx "gcr.io/${PROJECT_ID}/nginx:latest" docker push "gcr.io/${PROJECT_ID}/nginx:latest"
    1. 現在の GCR リポジトリにある「限定公開」の nginx イメージを表示します。
    gcloud container images list-tags "gcr.io/${PROJECT_ID}/nginx"

    タスク 7. すべてのイメージを禁止する

    ポリシーによるイメージの禁止が想定どおりに機能することを実証するために、まず、クラスタ固有の allow ルールが適用されており、すべてのコンテナの実行が許可されることを確認します。

    1. そのためには、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」というメッセージが表示されます。

    1. Pod を一覧表示します。
    kubectl get pods

    出力:

    NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 1m

    失敗した場合は、クラスタ固有のルールのリージョンと名前を再確認してやり直します。

    1. 完了したら、この Pod を削除します。
    kubectl delete pod nginx
    1. 次に、望ましくないイメージが Binary Authorization ポリシーによってブロックされてクラスタ内で実行されないことを確認します。

    [Binary Authorization] ページで [ポリシーを編集] をクリックします。

    1. GKE クラスタ固有のルールの右にあるその他アイコン(3 つの点)、[編集] の順にクリックします。

    2. 次に、[すべてのイメージを禁止] を選択し、[送信] をクリックします。

    ポリシーが次のようになります。

    [すべてのイメージを禁止] オプションを選択した状態の「us-central1-a.mycluster-1 に関する GKE クラスタ固有のルールの編集」ダイアログ ボックス

    1. 最後に、[ポリシーを保存] をクリックしてこれらの変更を適用します。
    注: ポリシーが有効になるまで少なくとも 30 秒待ってから次に進んでください。

    完了したタスクをテストする

    [進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization ポリシーが正常に更新されて、クラスタレベルのルールが [すべてのイメージを禁止] に変更されている場合は、評価スコアが表示されます。

    クラスタ固有のルールを [すべてのイメージを禁止] に変更する
    1. 次に、先ほどと同じコマンドを実行して静的な 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 監査ログに移動して、このアクティビティに関連するエラー メッセージでフィルタします。

    1. Google Cloud コンソールで、ナビゲーション メニュー > [ロギング] > [ログ エクスプローラ] に移動します。
    2. クエリビルダー ボックスに次のコードを入力します。
    resource.type="k8s_cluster" protoPayload.response.reason="VIOLATES_POLICY"

    コードを入力した状態のクエリビルダー

    1. [クエリを実行] をクリックします。
    2. nginx Pod の実行のブロックに対応するエラーが表示されます。

    完了したタスクをテストする

    [進行状況を確認] をクリックして、実行したタスクを確認します。クラスタ アドミッション ルールの確認が正常に行われた場合は、評価スコアが表示されます。

    Nginx Pod を作成して、すべてのイメージを禁止する(作成を拒否する)クラスタ アドミッション ルールが適用されていることを確認する

    タスク 8. 許可リストに登録されているコンテナ レジストリ以外のイメージを禁止する

    1. この nginx コンテナのみに実行を許可したい場合はどうすればよいでしょうか。最も簡単な方法は、このコンテナのソースであるレジストリを許可リストに登録することです。

    2. 次のコマンドの出力をイメージパスとして使用します。

    echo "gcr.io/${PROJECT_ID}/nginx*"
    1. イメージパスの出力をバッファにコピーします。

    2. ナビゲーション メニュー > [セキュリティ] > [Binary Authorization] に移動します。

    3. Binary Authorization ポリシーを編集します。[カスタム除外ルール] イメージパスが表示されてから、[イメージ パターンを追加] をクリックします。

    4. 先ほどコピーしたイメージパスを貼り付けて、[完了] をクリックします。次の図は、パスの例を示しています。

    新しいイメージ パターン フィールドでイメージパスが入力された Binary Authorization 画面

    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 を起動できるはずです。これにより、レジストリの許可リストが正常に機能していることがわかります。

    1. クリーンアップと次のステップの準備のために次のコマンドを実行します。
    kubectl delete pod nginx

    完了したタスクをテストする

    [進行状況を確認] をクリックして、実行したタスクを確認します。Binary Authorization ポリシーが正常に更新されて、コンテナ レジストリが許可リストに登録されている場合は、評価スコアが表示されます。

    Binary Authorization ポリシーを更新して、許可リストに登録されているコンテナ レジストリ(現在のプロジェクトのコンテナ レジストリ)以外のイメージを禁止する

    タスク 9. 証明書を必須にする

    コンテナ イメージ レジストリを許可リストに登録することは、望ましくないコンテナ イメージがクラスタ内で実行されるのを防ぐための最初のステップとして効果的ですが、コンテナが正しくビルドされていることを確認するためにできることは他にもあります。

    たとえば、特定のコンテナ イメージのデプロイが承認されているかどうかを暗号によって確認できます。これには「証明書の認証局」を使用します。証明書の認証局は、特定のステップが完了したことを証明するために、コンテナ イメージの SHA256 ハッシュを記述するメタデータのスニペットに PGP 鍵で署名して、それを一元的なメタデータ リポジトリ(Container Analysis API)に送信します。

    その後、コンテナ イメージの実行が許可されているかどうかをアドミッション コントローラが確認します。これは、イメージに証明書が存在することを要件とする Binary Authorization ポリシーを調べることによって行われます。このとき、完了したステップを示す署名付きメタデータ スニペットが Container Analysis API に保持されているかどうかが確認されます。この情報により、アドミッション コントローラは、その Pod の実行を許可すべきかどうかを判断します。

    次に、コンテナ イメージに手動の証明書を適用します。人間の「証明書の認証局」として、コンテナ イメージへの署名に必要なすべてのステップを実行し、クラスタ内で実行されるイメージに証明書が存在することを要求するポリシーを作成して、署名したイメージが Pod で正常に実行されることを確認します。

    必要な変数を設定する

    1. 認証者の詳細(名前とメールアドレス)を設定します。
    ATTESTOR="manually-verified" # スペースは使用できません ATTESTOR_NAME="Manual Attestor" ATTESTOR_EMAIL="$(gcloud config get-value core/account)" # これにより現在のユーザーとメールアドレスが使用されます
    1. 証明書の認証局の Container Analysis メモの ID と説明を設定します。
    NOTE_ID="Human-Attestor-Note" # スペースは使用できません NOTE_DESC="Human Attestation Note Demo"
    1. ペイロードとリクエストを作成するためのファイルの名前を設定します。
    NOTE_PAYLOAD_PATH="note_payload.json" IAM_REQUEST_JSON="iam_request.json"

    証明書のメモを作成する

    まず、証明書の認証局を Container Analysis メモとして Container Analysis API に登録します。そのためには、ATTESTATION メモを作成して Container Analysis API に送信します。

    1. ATTESTATION メモのペイロードを作成します。
    cat > ${NOTE_PAYLOAD_PATH} << EOF { "name": "projects/${PROJECT_ID}/notes/${NOTE_ID}", "attestation_authority": { "hint": { "human_readable_name": "${NOTE_DESC}" } } } EOF
    1. 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 鍵を適切に保護する必要があります。
    1. 別のシェル変数を設定します。
    PGP_PUB_KEY="generated-key.pgp"
    1. PGP 鍵を作成します。
    sudo apt-get install rng-tools sudo rngd -r /dev/urandom gpg --quick-generate-key --yes ${ATTESTOR_EMAIL}
    1. Enter キーを押して空のパスフレーズを使用し、表示される警告を承諾します。

    2. 公開 PGP 鍵を抽出します。

    gpg --armor --export "${ATTESTOR_EMAIL}" > ${PGP_PUB_KEY}

    Binary Authorization API で認証者を登録する

    次に、Binary Authorization API で「認証者」を作成して公開 PGP 鍵を追加します。

    1. Binary Authorization API で認証者を作成します。
    gcloud --project="${PROJECT_ID}" \ beta container binauthz attestors create "${ATTESTOR}" \ --attestation-authority-note="${NOTE_ID}" \ --attestation-authority-note-project="${PROJECT_ID}"
    1. 認証者に PGP 鍵を追加します。
    gcloud --project="${PROJECT_ID}" \ beta container binauthz attestors public-keys add \ --attestor="${ATTESTOR}" \ --pgp-public-key-file="${PGP_PUB_KEY}"
    1. 新たに作成された認証者を表示します。
    gcloud --project="${PROJECT_ID}" \ beta container binauthz attestors list

    出力は次のようになります。

    NAME: manually-verified NOTE: projects//notes/Human-Attestor-Note NUM_PUBLIC_KEYS: 1

    タスク 10. コンテナ イメージに「署名」する

    これまでのステップと次以降のステップを実行するのは 1 回だけですが、このステップは新しいコンテナ イメージを作成するたびに実行する必要があります。

    gcr.io/google-containers/nginx:latestnginx イメージは、すでにビルドされて使用できる状態になっています。このイメージに対して、独自のプロセスによってビルドされた独自のイメージの場合と同様に、手動の証明書を適用します。これにより、イメージをビルドする手間を省くことができます。

    1. シェル変数をいくつか設定します。
    GENERATED_PAYLOAD="generated_payload.json" GENERATED_SIGNATURE="generated_signature.pgp"
    1. PGP フィンガープリントを取得します。
    PGP_FINGERPRINT="$(gpg --list-keys ${ATTESTOR_EMAIL} | head -2 | tail -1 | awk '{print $1}')"
    1. このコンテナ イメージの SHA256 ダイジェストを取得します。
    IMAGE_PATH="gcr.io/${PROJECT_ID}/nginx" IMAGE_DIGEST="$(gcloud container images list-tags --format='get(digest)' $IMAGE_PATH | head -1)"
    1. JSON 形式の署名ペイロードを作成します。
    gcloud beta container binauthz create-signature-payload \ --artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" > ${GENERATED_PAYLOAD}
    1. 生成された署名ペイロードを表示します。
    cat "${GENERATED_PAYLOAD}"
    1. PGP 鍵を使用してペイロードに「署名」します。
    gpg --local-user "${ATTESTOR_EMAIL}" \ --armor \ --output ${GENERATED_SIGNATURE} \ --sign ${GENERATED_PAYLOAD}
    1. 生成された署名(PGP メッセージ)を表示します。
    cat "${GENERATED_SIGNATURE}"
    1. 証明書を作成します。
    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}"
    1. 新たに作成された証明書を表示します。
    gcloud beta container binauthz attestations list \ --attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}"

    タスク 11. 証明書の必須化を有効にしてイメージを実行する

    次に、Binary Authorization ポリシーを変更して、許可リストのパターンに一致しないすべてのイメージで証明書の存在を必須にします。

    1. 証明書を要求するようにポリシーを変更するには、まず、次のコマンドを実行して、証明書の認証局のフルパスと名前をコピーします。
    echo "projects/${PROJECT_ID}/attestors/${ATTESTOR}" # この出力をコピー / 貼り付けバッファにコピーします
    1. 次に、Binary Authorization ポリシーを編集して、GKE クラスタ固有のルールを編集します。

    現在のクラスタ名の横にあるその他アイコン(3 つの点)をクリックして、[編集] を選択します。

    1. ポップアップ ウィンドウの [すべてのイメージを禁止] の代わりに、[証明書を要求: 次の認証者によって検証されたイメージのみを許可します] を選択します。

    [すべてのイメージを禁止] オプションを選択した状態のポリシーの編集ページ

    1. 次に、[認証者の追加] をクリックし、[認証者リソース ID により追加] をクリックします。コピー / 貼り付けバッファの内容を projects/${PROJECT_ID}/attestors/${ATTESTOR} という形式で入力し、[認証者の追加]、[送信]、[ポリシーを保存] の順にクリックします。

    「us-central1-a.my-cluster-1 に関する GKE クラスタ固有のルールの編集」ダイアログ ボックス

    デフォルトのポリシーは [すべてのイメージを禁止] のままですが、クラスタ固有のルールでは証明書が要求されています。

    1. 次に、前のステップで署名したイメージの最新の SHA256 ダイジェストを取得します。
    IMAGE_PATH="gcr.io/${PROJECT_ID}/nginx" IMAGE_DIGEST="$(gcloud container images list-tags --format='get(digest)' $IMAGE_PATH | head -1)"
    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 で確認できます。

    1. 「ブレークグラス」アノテーションを使用して未署名の 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
    1. Google Cloud コンソールで、ナビゲーション メニュー > [ロギング] > [ログ エクスプローラ] ページに移動します。

    2. クエリビルダー ボックスに次のコードを入力し、[クエリを実行] をクリックします。

      resource.type="k8s_cluster" protoPayload.request.metadata.annotations."alpha.image-policy.k8s.io/break-glass"="true"
    3. 前述のアノテーションによって Pod が許可された場合は、イベントが表示されます。このフィルタからシンクを作成して、このフィルタに一致するログを外部の宛先に送信できます。

    コードを入力した状態のクエリビルダーのテキスト ボックス

    注: ログが表示されるまで、少なくとも 5~10 分かかります。

    タスク 13. 破棄

    このラボで作成したすべてのリソースは Qwiklabs によって削除されますが、実際の環境をクリーンアップする方法を学習しておきましょう。

    1. 次のスクリプトで Kubernetes Engine クラスタを破棄します。
    ./delete.sh -c my-cluster-1

    このラボの始めに独自のクラスタ名を指定した場合はその名前を使用してください。この例で使用されている名前は my-cluster-1 です。

    出力の最後の行が次のようになります。

    Deleting cluster 注: クラスタの削除コマンドは非同期で実行され、完了までにしばらくかかります。進捗状況を追跡するには、Cloud コンソール UI または gcloud container clusters list コマンドを使用します。クラスタが削除されるまで待ちます。

    完了したタスクをテストする

    [進行状況を確認] をクリックして、実行したタスクを確認します。クラスタが正常に削除された場合は、評価スコアが表示されます。

    破棄する(クラスタを削除する)

    以下のコマンドで残りのリソースを削除します。

    1. GCR に push したコンテナ イメージを削除します。
    gcloud container images delete "${IMAGE_PATH}@${IMAGE_DIGEST}" --force-delete-tags
    1. [Do you want to continue (Y/n)] というメッセージが表示されたら、「Y」と入力します。

    2. 認証者を削除します。

    gcloud --project="${PROJECT_ID}" \ beta container binauthz attestors delete "${ATTESTOR}"
    1. Container Analysis メモを削除します。
    curl -X DELETE \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/${NOTE_ID}"

    独自の環境でのトラブルシューティング

    1. Binary Authorization ポリシーを更新してすぐに新しい Pod やコンテナを起動しようとすると、ポリシーがまだ有効になっていないことがあります。ポリシーの変更が有効になるまでには 30 秒以上かかる場合があります。再試行するには、kubectl delete <podname> を使用して Pod を削除してから Pod 作成コマンドを再送信します。
    2. クラスタのステータスを確認するには gcloud container clusters list コマンドを実行します。
    3. 追加機能を有効にした場合は(--enable-network-policy--accelerator--enable-tpu--enable-metadata-concealment など)、Binary Authorization ポリシーの許可リストにレジストリをさらに追加しないと Pod を実行できない可能性があります。kubectl describe pod <podname> を使用してイメージ仕様でレジストリパスを確認し、gcr.io/example-registry/* という形式で許可リストに追加してポリシーを保存します。
    4. 割り当てに関するエラーが表示された場合は、プロジェクトの割り当てを増やしてください。リソースの割り当ての詳細については、リソースの割り当てに関するドキュメントをご覧ください。

    関連資料

    1. Google Cloud の割り当て
    2. Google Cloud への登録
    3. Google Cloud Shell
    4. GKE の Binary Authorization
    5. Container Analysis のメモ
    6. Kubernetes アドミッション コントローラ
    7. リリース ステージ

    お疲れさまでした

    クエストを完了する

    このセルフペース ラボは、Qwiklabs の「Google Kubernetes Engine Best Practices: Security」クエストの一部です。クエストとは学習プログラムを構成する一連のラボのことで、完了すると成果が認められてバッジが贈られます。バッジは公開して、オンライン レジュメやソーシャル メディア アカウントにリンクできます。このクエストに登録すれば、すぐにクレジットを受け取ることができます受講可能なすべてのクエストについては、Google Cloud Skills Boost カタログをご覧ください。

    次のラボを受講する

    Google Kubernetes Engine でのネットワーク ポリシーの使用方法」に進んでクエストを続けるか、以下のおすすめをご確認ください。

    マニュアルの最終更新日: 2023 年 10 月 11 日

    ラボの最終テスト日: 2023 年 10 月 11 日

    Copyright 2024 Google LLC. 本ソフトウェアは「現状有姿」で提供されており、いかなる使用および目的に関しても保証および表明は伴いません。本ソフトウェアのご利用には、Google との契約が適用されます。