このチュートリアルでは、証明書を要求する Binary Authorization ポリシーの構成とテストの方法を説明します。このタイプのポリシーは、イメージのデプロイを許可する前に、コンテナ イメージに署名付き証明書があることを確認して、コンテナベースのソフトウェア サプライ チェーンを保護します。
デプロイ時に、Binary Authorization は認証者を使用して証明書のデジタル署名を検証します。証明書は、通常は継続的インテグレーション(CI)パイプラインの一部として署名者によって作成されます。
このチュートリアルでは、GKE クラスタ、証明書、認証者はすべて 1 つのプロジェクトに存在します。単一プロジェクト構成はサービスのテストや試験運用に非常に役立ちます。より現実的な例については、マルチプロジェクト構成をご覧ください。
以下では、コマンドラインで実行するタスクについて説明します。以下の手順を Google Cloud コンソールで行うには、Google Cloud コンソールの使用を開始するをご覧ください。
目標
このチュートリアルでは、以下の方法について学習します。
- Binary Authorization を有効にして Google Kubernetes Engine(GKE)クラスタを作成する
- Binary Authorization 施行者が証明書の署名を検証するために使用する認証者を作成する
- 証明書を要求するポリシーを構成する
- 証明書に署名して後で検証するための暗号鍵ペアを作成する
- 署名を作成してコンテナ イメージ ダイジェストに署名する
- 署名を使用して証明書を作成する
- コンテナ イメージを GKE にデプロイしてポリシーをテストする
費用
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
- Artifact Registry or Container Registry
- Binary Authorization
- GKE
- Optional: Cloud Key Management Service
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
始める前に
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
- GKE を操作するために
kubectl
をインストールします。
Binary Authorization を有効にする
デフォルト プロジェクトを設定する
まず、gcloud
コマンドでデフォルトの Google Cloud プロジェクトを設定します。
PROJECT_ID=PROJECT_ID gcloud config set project ${PROJECT_ID}
ここで PROJECT_ID はプロジェクトの名前です。
必要な API を有効にする
以下の API を有効にします。
Container Registry
gcloud --project=${PROJECT_ID} \ services enable\ container.googleapis.com\ containerregistry.googleapis.com\ binaryauthorization.googleapis.com
Artifact Registry
gcloud --project=${PROJECT_ID} \ services enable\ container.googleapis.com\ artifactregistry.googleapis.com\ binaryauthorization.googleapis.com
Binary Authorization を有効にしたクラスタを作成する
クラスタを作成する
Binary Authorization を有効にした GKE クラスタを作成します。このクラスタで、デプロイしたコンテナ イメージを実行します。クラスタを作成するときに、--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
フラグを gcloud container clusters create
コマンドに渡します。
クラスタの作成手順は次のとおりです。
gcloud container clusters create \ --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \ --zone us-central1-a \ test-cluster
ここでは、GKE ゾーン us-central1-a
に test-cluster
というクラスタを作成します。
kubectl
を構成する
kubectl
のインストール用にローカルの kubeconfig
ファイルも更新する必要があります。これにより、GKE でクラスタにアクセスするために必要な認証情報とエンドポイント情報が提供されます。
ローカル kubeconfig
ファイルを更新するには:
gcloud container clusters get-credentials \ --zone us-central1-a \ test-cluster
デフォルトのポリシーを表示する
Binary Authorization ポリシーは、コンテナ イメージのデプロイを制御する一連のルールです。プロジェクトごとに 1 つのポリシーを作成できます。デフォルトでは、すべてのコンテナ イメージをデプロイできるポリシーが構成されています。
Binary Authorization を使用すると、YAML 形式のポリシー ファイルをエクスポートまたはインポートできます。この形式は、サービスによって保存されたポリシーの構造を反映しています。gcloud
コマンドでポリシーを構成する場合は、このファイルを編集します。
デフォルト ポリシーを表示するには、ポリシーの YAML ファイルをエクスポートします。
gcloud container binauthz policy export
デフォルトでは、このファイルの内容は次のようになっています。
defaultAdmissionRule: enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG evaluationMode: ALWAYS_ALLOW globalPolicyEvaluationMode: ENABLE name: projects/PROJECT_ID/policy
デフォルト ルールは defaultAdmissionRule
ノードに定義されています。evaluationMode
は、イメージのデプロイ時にすべての試行を許可することを指定します。このチュートリアルでは、証明書を要求するようにデフォルト ルールを更新します。
globalPolicyEvaluationMode
は、Google 管理のシステム イメージを Binary Authorization の適用対象から除外します。
除外イメージを許可リストに追加するには、ポリシー ファイルに次の行を追加します。
admissionWhitelistPatterns: - namePattern: EXEMPT_IMAGE_PATH
EXEMPT_IMAGE_PATH
は、除外するイメージのパスに置き換えます。除外するイメージを追加するには、- namePattern
エントリを追加します。admissionWhitelistPatterns
の詳細をご確認ください。
ポリシーの構造については、ポリシー YAML リファレンスをご覧ください。
認証者を作成する
認証者は、デプロイ時に Binary Authorization 施行者が GKE で対応する署名付きコンテナ イメージのデプロイを許可するかどうかを決定する際に使用する検証機関です。認証者には公開鍵が含まれ、通常は、ソフトウェア サプライ チェーンのセキュリティを担当する組織の担当者が管理します。
認証者を作成するには、次のことを行います。
- Artifact Analysis でメモを作成して、認証プロセスで使用される信頼できるメタデータを保存する
- Binary Authorization で認証者を作成し、作成したメモを関連付ける
このチュートリアルでは、test-attestor
という認証者と test-attestor-note
という Container Analysis メモを使用しています。実際のシナリオでは、任意の数の認証者を指定できます。各認証者は、コンテナ イメージの認証プロセスに参加する当事者を表します。
Artifact Analysis メモを作成する
認証者の名前と Artifact Analysis メモを格納する変数を設定します。
ATTESTOR_NAME=test-attestor NOTE_ID=test-attestor-note
次のように置き換えます。
- test-attestor: 選択した認証者の名前。
- attestor-note: 選択した認証者のメモ名。
Container Analysis メモを記述する JSON ファイルを
/tmp/note_payload.json
に作成します。cat > /tmp/note_payload.json << EOM { "name": "projects/${PROJECT_ID}/notes/${NOTE_ID}", "attestation": { "hint": { "human_readable_name": "Attestor Note" } } } EOM
HTTP リクエストを Artifact Analysis REST API に送信して、メモを作成します。
curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ --data-binary @/tmp/note_payload.json \ "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
メモが作成されたことを確認します。
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
認証者を作成する
これで認証者を作成できます。
Binary Authorization で認証者を作成します。
gcloud container binauthz attestors create ${ATTESTOR_NAME} \ --attestation-authority-note=${NOTE_ID} \ --attestation-authority-note-project=${PROJECT_ID}
認証者が作成されたことを確認します。
gcloud container binauthz attestors list
作成した認証者は、以下で作成する PKIX 鍵ペアが関連付けられていないため、まだ使用できません。
鍵ペアを生成する
Binary Authorization は、暗号鍵を使用して署名者の ID を安全に確認します。これにより、承認済みのコンテナ イメージのみをデプロイできます。鍵ペアは秘密鍵と公開鍵で構成されます。署名者は、署名を生成して証明書に保存し、秘密鍵を使用してコンテナ イメージのダイジェストに署名します。公開鍵は認証者に保存されます。コンテナのデプロイを許可する前に、Binary Authorization の施行者が認証者の公開鍵を使用して、証明書の署名を検証します。
このチュートリアルでは、暗号鍵に公開鍵基盤(X.509)(PKIX)形式を使用します。このチュートリアルでは、PKIX 鍵ペアの生成に推奨の 楕円曲線デジタル署名アルゴリズム(ECDSA)を使用していますが、RSA 鍵または PGP 鍵で署名することもできます。
署名アルゴリズムの詳細については、鍵の目的とアルゴリズムをご覧ください。
Cloud Key Management Service(Cloud KMS)によって生成され、保存された鍵は PKIX に準拠しています。PKIX 鍵と Cloud KMS の使用方法については、gcloud CLI を使用した認証者の作成をご覧ください。
PKIX(Cloud KMS)
Cloud KMS で鍵ペアを作成する手順は次のとおりです。
鍵ペアの作成に必要な環境変数を設定します。
KMS_KEY_PROJECT_ID=${PROJECT_ID} KMS_KEYRING_NAME=my-binauthz-keyring KMS_KEY_NAME=my-binauthz-kms-key-name KMS_KEY_LOCATION=global KMS_KEY_PURPOSE=asymmetric-signing KMS_KEY_ALGORITHM=ec-sign-p256-sha256 KMS_PROTECTION_LEVEL=software KMS_KEY_VERSION=1
キーリングを作成するには、次のコマンドを実行します。
gcloud kms keyrings create ${KMS_KEYRING_NAME} \ --location ${KMS_KEY_LOCATION}
鍵を作成するには、次のコマンドを実行します。
gcloud kms keys create ${KMS_KEY_NAME} \ --location ${KMS_KEY_LOCATION} \ --keyring ${KMS_KEYRING_NAME} \ --purpose ${KMS_KEY_PURPOSE} \ --default-algorithm ${KMS_KEY_ALGORITHM} \ --protection-level ${KMS_PROTECTION_LEVEL}
認証者に公開鍵を追加するには、次のコマンドを実行します。
gcloud --project="${PROJECT_ID}" \ container binauthz attestors public-keys add \ --attestor="${ATTESTOR_NAME}" \ --keyversion-project="${KMS_KEY_PROJECT_ID}" \ --keyversion-location="${KMS_KEY_LOCATION}" \ --keyversion-keyring="${KMS_KEYRING_NAME}" \ --keyversion-key="${KMS_KEY_NAME}" \ --keyversion="${KMS_KEY_VERSION}"
次のように、認証者から公開鍵 ID を取得します。
公開鍵 ID は、
gcloud container binauthz attestors describe <var>ATTESTOR_NAME</var>
コマンドでいつでも確認できます。公開鍵 ID を環境変数に格納するには、次のコマンドを入力します。
PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \ --format='value(userOwnedGrafeasNote.publicKeys[0].id)' --project ${PROJECT_ID})
PKIX(ローカル鍵)
PKIX 鍵ペアの生成手順は次のとおりです。
秘密鍵を作成します。
PRIVATE_KEY_FILE="/tmp/ec_private.pem" openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
秘密鍵から公開鍵を抽出します。
PUBLIC_KEY_FILE="/tmp/ec_public.pem" openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
認証者に公開鍵を追加します。
次に、エクスポートした公開鍵を認証者に追加して、Binary Authorization で本人確認に使用できるようにします。
gcloud --project="${PROJECT_ID}" \ beta container binauthz attestors public-keys add \ --attestor="${ATTESTOR_NAME}" \ --pkix-public-key-file=${PUBLIC_KEY_FILE} \ --pkix-public-key-algorithm=ecdsa-p256-sha256
公開鍵 ID を保存します。
公開鍵 ID を保存するには、上記の
public-keys add
の出力から ID をコピーします。認証者に追加した公開鍵 ID を表示するには、gcloud container binauthz attestors describe ${ATTESTOR_NAME}
を使用します。PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \ --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
ポリシーを構成する
これで、ポリシーを構成できます。この手順では、ポリシー YAML ファイルをローカル システムにエクスポートし、上記で定義した認証者による証明書を要求するようにデフォルト ルールを変更します。
ポリシーの構成手順は次のとおりです。
Google 管理のシステム イメージを許可する新しいポリシー ファイルを作成します。
evaluationMode
にREQUIRE_ATTESTATION
を設定し、作成した認証者を参照するノードをrequireAttestationsBy
という名前で追加します。cat > /tmp/policy.yaml << EOM globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: REQUIRE_ATTESTATION enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG requireAttestationsBy: - projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME} name: projects/${PROJECT_ID}/policy EOM
ポリシー YAML ファイルを Binary Authorization にインポートします。
gcloud container binauthz policy import /tmp/policy.yaml
ポリシーの構成の詳細については、gcloud CLI を使用してポリシーを構成するをご覧ください。
ポリシーのテスト
上記で構成したポリシーをテストするには、サンプル コンテナ イメージをクラスタにデプロイします。必要な証明書が作成されていないため、ポリシーによってデプロイがブロックされます。
このチュートリアルでは、Container Registry と Artifact Registry のサンプル イメージを使用できます。Container Registry のイメージは、パス gcr.io/google-samples/hello-app:1.0
にあります。Artifact Registry のイメージはパス us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
にあります。どちらのパスにも、「Hello, World!」サンプル アプリケーションを含む Google 作成の公開イメージが含まれています。
まず、イメージをデプロイします。
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
次に、Binary Authorization でデプロイがブロックされたことを確認します。
kubectl get pods
このコマンドを実行すると、イメージがデプロイされなかったことを示す次のメッセージが出力されます。
No resources found.
次のコマンドによってデプロイの詳細を確認できます。
kubectl get event --template \ '{{range.items}}{{"\033[0;36m"}}{{.reason}}:{{"\033[0m"}}\{{.message}}{{"\n"}}{{end}}'
次のようなレスポンスが表示されます。
FailedCreate: Error creating: pods POD_NAME is forbidden: admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image IMAGE_NAME denied by Binary Authorization default admission rule. Image IMAGE_NAME denied by attestor ATTESTOR_NAME: No attestations found
この出力で:
- POD_NAME: Pod の名前。
- IMAGE_NAME: イメージの名前。
- ATTESTOR_NAME: 認証者の名前。
デプロイを削除して次の手順に進みます。
kubectl delete deployment hello-server
証明書を作成する
証明書は、関連するコンテナ イメージのデプロイを GKE が許可されていることを証明する、署名者によって作成されるデジタル ドキュメントです。証明書を作成するプロセスを「イメージに署名する」という場合があります。署名者は人の場合もあれば、コンテナ イメージのビルド時に実行される自動プロセスである場合もあります。署名は、鍵ペアの秘密鍵を使用して作成されます。デプロイ時に、Binary Authorization 施行者は認証者の公開鍵を使用して証明書の署名を検証します。
このチュートリアルでは、イメージのデプロイが承認されていることのみを証明します。
証明書の作成手順は次のとおりです。
イメージのレジストリパスとダイジェストを格納する変数を設定します。
Container Registry
IMAGE_PATH="gcr.io/google-samples/hello-app" IMAGE_DIGEST="sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea882eb722c3be4" IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
Artifact Registry
IMAGE_PATH="us-docker.pkg.dev/google-samples/containers/gke/hello-app" IMAGE_DIGEST="sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567" IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
証明書の作成手順は次のとおりです。
PKIX Cloud KMS
Cloud KMS 鍵を使用して証明書を作成するには、次のコマンドを実行します。
gcloud beta container binauthz attestations sign-and-create \ --project="${PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="${ATTESTOR_NAME}" \ --attestor-project="${PROJECT_ID}" \ --keyversion-project="${KMS_KEY_PROJECT_ID}" \ --keyversion-location="${KMS_KEY_LOCATION}" \ --keyversion-keyring="${KMS_KEYRING_NAME}" \ --keyversion-key="${KMS_KEY_NAME}" \ --keyversion="${KMS_KEY_VERSION}"
PKIX(ローカル鍵)
ローカル鍵を使用して証明書を作成する手順は次のとおりです。
証明書ペイロードを生成します。
gcloud container binauthz create-signature-payload \ --artifact-url=${IMAGE_TO_ATTEST} > /tmp/generated_payload.json
ペイロード JSON ファイルの内容は次のとおりです。
{ "critical": { "identity": { "docker-reference": "gcr.io/google-samples/hello-app" }, "image": { "docker-manifest-digest": "sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea 882eb722c3be4" }, "type": "Google cloud binauthz container signature" } }
PKIX 秘密鍵でペイロードに署名し、署名ファイルを生成するには、次のコマンドを実行します。
openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
この署名ファイルは、このガイドの前半で作成したペイロード JSON ファイルの署名付きバージョンです。
証明書を作成して検証します。
gcloud container binauthz attestations create \ --project="${PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --signature-file=/tmp/ec_signature \ --public-key-id="${PUBLIC_KEY_ID}" \ --validate
PUBLIC_KEY_ID
は、上記の PKIX 鍵ペアを生成するにある公開鍵 ID に置き換えます。validate
フラグは、ポリシーで構成した認証者が証明書を検証できることを確認します。
証明書が作成されたことを確認します。
gcloud container binauthz attestations list \ --attestor=$ATTESTOR_NAME --attestor-project=$PROJECT_ID
証明書の作成の詳細については、証明書の作成をご覧ください。
ポリシーを再テストする
クラスタにサンプル コンテナ イメージをデプロイして、ポリシーを再度テストします。今回は、Binary Authorization はダイジェストを使用して証明書を検索するため、1.0
や latest
などのタグではなく、ダイジェストを使用してイメージをデプロイする必要があります。ここでは、必要な証明書が作成されたため、Binary Authorization はイメージのデプロイを許可します。
イメージのデプロイ手順は次のとおりです。
kubectl run hello-server --image ${IMAGE_TO_ATTEST} --port 8080
イメージがデプロイされたことを確認するには:
kubectl get pods
このコマンドを実行すると、デプロイが成功したことを示す次のようなメッセージが出力されます。
NAME READY STATUS RESTARTS AGE hello-server-579859fb5b-h2k8s 1/1 Running 0 1m
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
GKE で作成したクラスタを削除します。
gcloud container clusters delete \ --zone=us-central1-a \ test-cluster