Binary Authorization は、単一プロジェクト構成またはマルチプロジェクト構成で設定できます。マルチプロジェクト構成では、さまざまなロールを担当する複数のユーザーがソフトウェア サプライチェーン ワークフローのさまざまなステージを担当します。この構成は Binary Authorization の使用に適しています。この構成は、職掌分散ともいいます。たとえば、次のようなロールがあります。
デプロイ担当者: 会社のポリシーに従ってアプリケーションを GKE にデプロイする個人または自動プロセス。ここでは、ソフトウェアのデプロイに焦点を当てます。通常、この機能はソフトウェア エンジニアまたは DevOps エンジニアが担当します。
セキュリティ オペレーション(SecOps)マネージャー: Binary Authorization が会社のポリシーに従って証明書が必要なポリシー ルールを適用する際に使用する承認済みの鍵を管理する担当者。この担当者は、ポリシー、ルール、認証者を作成することもできます。これらの認証者が最終的に証明書を検証し、コンテナが GKE にデプロイできるようにします。そのため、このロールにのみ認証者への書き込みが許可されます。
証明書マネージャー: 認証者が必要とする証明書を作成し、管理する担当者。暗号鍵の生成と管理を行います。さらに、コンテナ イメージ記述子を署名して、証明書を作成します。証明書の管理も行います。
このチュートリアルでは、上記のロールごとに異なるプロジェクトを設定します。デプロイ担当者のロールにはデプロイ担当者プロジェクトを設定し、セキュリティ マネージャーのロールには認定者プロジェクトを設定します。また、証明書マネージャーには証明書プロジェクトを設定します。
次に、証明書を要求するルールを含む Binary Authorization ポリシーを構成します。最後に、デプロイのテストを行います。
各プロジェクトには、Identity and Access Management(IAM)による適切なアクセス制御が構成されます。
このチュートリアルで作成したリソースを VPC Service Controls で保護すると、セキュリティを強化できます。詳細については、VPC Service Controls による保護をご覧ください。
デプロイ担当者プロジェクトを設定する
まず、デプロイ担当者プロジェクトを設定します。
デプロイ担当者プロジェクトでは、イメージがデプロイされる Google Kubernetes Engine(GKE)クラスタとデプロイを制御する Binary Authorization ポリシーを管理します。環境の規模、複雑さ、その他の要件に応じて、複数のデプロイ担当者プロジェクトを使用できます。
デプロイ担当者プロジェクトを設定するには:
Google Cloud Console でプロジェクトを作成し、課金を有効にします(まだ有効にしていない場合)。
Identity and Access Management に関する注: デプロイ担当者プロジェクトには GKE クラスタが含まれます。このプロジェクトの Identity and Access Management の構成にも、このことが反映されている必要があります。
プロジェクト名と番号を格納する環境変数を設定します。
DEPLOYER_PROJECT_ID=PROJECT_ID
PROJECT_ID は Google Cloud プロジェクトの名前です。
DEPLOYER_PROJECT_NUMBER=$(gcloud projects describe "${DEPLOYER_PROJECT_ID}" \ --format="value(projectNumber)")
Binary Authorization API と GKE API を有効にします。
gcloud --project=${DEPLOYER_PROJECT_ID} \ services enable \ container.googleapis.com \ binaryauthorization.googleapis.com
デプロイ担当者プロジェクトのサービス アカウント名を取得します。
DEPLOYER_SERVICE_ACCOUNT="service-${DEPLOYER_PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
サービス アカウント名は、後の手順で認証者に関連付けられた Container Analysis メモの権限を構成する際に使用します。
認証者プロジェクトを設定する
認証者プロジェクトには、イメージをデプロイする準備ができていることを確認できる認証者が保存されます。認証プロセスで信頼できる関係者に関する情報を一元的に保管する場所として単一の認証者プロジェクトを作成できます。この場合、認証者の ID を検証するために必要なセキュリティ キーを一元管理し、これらの鍵を管理する関係者にのみアクセスを許可できます。
認証者プロジェクトを設定するには:
Google Cloud Console でプロジェクトを作成し、課金を有効にします(まだ有効にしていない場合)。
Identity and Access Management に関する注: このプロジェクトには認証者が含まれているため、セキュリティ担当者にのみ書き込み権限を付与します。
プロジェクト名と番号を格納する環境変数を設定します。
ATTESTOR_PROJECT_ID=PROJECT_ID
PROJECT_ID は Google Cloud プロジェクトの名前です。
ATTESTOR_PROJECT_NUMBER=$(gcloud projects describe "${ATTESTOR_PROJECT_ID}" \ --format="value(projectNumber)")
Container Analysis API と Binary Authorization API を有効にします。
gcloud services --project=${ATTESTOR_PROJECT_ID} \ enable containeranalysis.googleapis.com \ binaryauthorization.googleapis.com
認証者プロジェクトのサービス アカウント名を取得します。
ATTESTOR_SERVICE_ACCOUNT="service-${ATTESTOR_PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
サービス アカウント名は、後の手順で認証者に関連付けられた Container Analysis メモの権限を構成する際に使用します。
証明書プロジェクトを設定する
証明書プロジェクトとは、証明書の検証で認証者が作成する証明書を保存するプロジェクトです。証明書プロジェクトを別に作成することで、ソフトウェアの準備状況に関する記述をより簡単に整理し、検査できます。
Google Cloud Console でプロジェクトを作成し、課金を有効にします(まだ有効にしていない場合)。
Identity and Access Management に関する注: Binary Authorization に関するすべてのロールに、このプロジェクトの Container Analysis のメモとオカレンスに対する読み取り権限が付与されますが、書き込み権限が必要になるのは証明書マネージャーだけです。
プロジェクト名を格納する環境変数を設定します。
ATTESTATION_PROJECT_ID=PROJECT_ID
PROJECT_ID は Google Cloud プロジェクトの名前です。
Container Analysis API と Binary Authorization API を有効にします。
gcloud services --project=${ATTESTATION_PROJECT_ID} \ enable containeranalysis.googleapis.com \ binaryauthorization.googleapis.com
クラスタを作成する
これで、デプロイ担当者プロジェクトに GKE クラスタを作成できます。このクラスタで、デプロイしたコンテナ イメージを実行します。クラスタを作成するときに、--enable-binauthz
フラグを gcloud beta container clusters create
コマンドに渡します。
クラスタを作成するには:
gcloud --project=${DEPLOYER_PROJECT_ID} \ beta container clusters create \ --enable-binauthz \ --zone us-central1-a \ test-cluster
ここでは、GKE ゾーン us-central1-a
に test-cluster
というクラスタを作成します。
kubectl
のインストール用にローカルの kubeconfig
ファイルも更新する必要があります。これにより、GKE でクラスタにアクセスするために必要な認証情報とエンドポイント情報が提供されます。
ローカル kubeconfig
ファイルを更新するには:
gcloud --project=${DEPLOYER_PROJECT_ID} \ container clusters get-credentials \ --zone us-central1-a \ test-cluster
認証者を作成する
認証者は、コンテナ イメージをデプロイする前に必要なプロセスが完了したことを証明する責任者です。これは、人の場合もあれば、ビルド / テストシステムなどのマシンプロセス、または継続的インテグレーション(CI)とデプロイ(CD)のパイプラインの場合もあります。認証者は認証者プロジェクトに作成します。
認証者を作成するには、次のことを行います。
- Container Analysis でメモを作成して、認証プロセスで使用される信頼できるメタデータを保存する
- 認証者プロジェクトで認証者を作成し、作成したメモを関連付ける
- デプロイ担当者プロジェクトのサービス アカウントの IAM ロール バインディングを認証者に追加する
- Container Analysis メモに権限を設定する
このチュートリアルでは、test-attestor
という認証者と test-attestor-note
という Container Analysis メモを使用しています。実際のシナリオでは、任意の数の認証者を指定できます。各認証者は、イメージの認証プロセスに参加する当事者を表します。
Container Analysis メモを作成する
認証者の名前と Container Analysis メモを格納する変数を設定します。
ATTESTOR_NAME=test-attestor NOTE_ID=test-attestor-note
Container Analysis メモを記述する JSON ファイルを
/tmp/note_payload.json
に作成します。cat > /tmp/note_payload.json << EOM { "name": "projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}", "attestation": { "hint": { "human_readable_name": "Attestor Note" } } } EOM
HTTP リクエストを Container 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/${ATTESTOR_PROJECT_ID}/notes/?noteId=${NOTE_ID}"
メモが作成されたことを確認します。
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}"
認証者を作成する
これで認証者を作成できます。
Binary Authorization で認証者を作成します。
gcloud --project=${ATTESTOR_PROJECT_ID} \ beta container binauthz attestors create ${ATTESTOR_NAME} \ --attestation-authority-note=${NOTE_ID} \ --attestation-authority-note-project=${ATTESTOR_PROJECT_ID}
認証者が作成されたことを確認します。
gcloud --project=${ATTESTOR_PROJECT_ID} \ beta container binauthz attestors list
作成した認証者は、以下で作成する PKIX 鍵ペアが関連付けられていないため、まだ使用できません。
デプロイ担当者プロジェクトの IAM ロール バインディングを追加する
デプロイ担当者プロジェクトの IAM ロール バインディングを認証者に追加する必要があります。これは、Binary Authorization がポリシーを評価して、関連する証明書にアクセスする権限があるかどうかを判定するときに使用されます。
IAM ロール バインディングを追加するには:
gcloud --project ${ATTESTOR_PROJECT_ID} \ beta container binauthz attestors add-iam-policy-binding \ "projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --member="serviceAccount:${DEPLOYER_SERVICE_ACCOUNT}" \ --role=roles/binaryauthorization.attestorsVerifier
Container Analysis メモに権限を設定する
また、デプロイ担当者プロジェクトと認証者プロジェクトの両方にアクセスできるように、作成した Container Analysis メモに権限を設定する必要があります。これを行うには、メモの IAM ポリシーを更新し、プロジェクト サービス アカウントに閲覧者のアクセス権を割り当てます。
メモに IAM ポリシーを設定するために必要な情報を含む JSON ファイルを生成します。
cat > /tmp/iam_request.json << EOM { 'resource': 'projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}', 'policy': { 'bindings': [ { 'role': 'roles/containeranalysis.notes.occurrences.viewer', 'members': [ 'serviceAccount:${ATTESTOR_SERVICE_ACCOUNT}' ] } ] } } EOM
作成したメモのサービス アカウントとリクエストされたアクセス ロールを IAM ポリシーに追加します。
curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ --data-binary @/tmp/iam_request.json \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"
PKIX 鍵を設定する
Binary Authorization では、暗号鍵を使用して認証者の ID を安全に確認します。これにより、確認済みの関係者だけがコンテナ イメージの認証に参加できます。鍵ペアは、認証者が証明書のデジタル署名に使用する秘密鍵と、Binary Authorization サービスによって保存され、認証者に追加される公開鍵で構成されます。
このチュートリアルでは、鍵ペアの作成に推奨の楕円曲線デジタル署名アルゴリズム(ECDSA)を使用していますが、RSA 鍵または PGP 鍵で署名することもできます。署名アルゴリズムの詳細については、鍵の目的とアルゴリズムをご覧ください。
Cloud Key Management Service(Cloud KMS)によって生成され、保存された非対称鍵は PKIX に準拠しています。PKIX 鍵と Cloud KMS の使用方法については、CLI を使用した認証者の作成をご覧ください。
鍵ペアを生成する
PKIX 鍵ペアは、署名者が証明書のデジタル署名に使用する公開鍵と、認証者に追加する公開鍵で構成されます。デプロイ時に、Binary Authorization はこの公開鍵を使用して秘密鍵で署名された証明書を検証します。
秘密鍵を生成します。
新しいローカル非対称 PKIX 鍵ペアを生成してファイルに保存するには:
PKIX(ローカルキー)
秘密鍵を生成します。
PRIVATE_KEY_FILE は、証明書ペイロードの署名に使用される秘密鍵を含むファイルの名前です。
PRIVATE_KEY_FILE="/tmp/ec_private.pem" openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
秘密鍵から公開鍵を抽出し、ファイルに保存します。
PUBLIC_KEY_FILE は、認証者に保存される公開鍵を含むファイルの名前です。
PUBLIC_KEY_FILE="/tmp/ec_public.pem" openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
- 認証者にローカル公開鍵を追加する
次に、エクスポートした公開鍵を認証者に追加して、Binary Authorization で本人確認に使用できるようにします。
gcloud --project="${ATTESTOR_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
PKIX(Cloud KMS)
このステップでは、Cloud Key Management Service で生成され、保存されている鍵を使用して認証を行う方法について説明します。
Cloud KMS で管理される鍵ペアに関する情報を格納する環境変数を設定します。
すでに鍵ペアがある場合は、これらの環境変数を設定した後、次の手順をスキップできます。
KMS_KEY_PROJECT_ID=KMS_KEY_PROJECT_ID KMS_KEY_LOCATION=KMS_KEY_LOCATION KMS_KEYRING_NAME=KMS_KEYRING_NAME KMS_KEY_NAME=KMS_KEY_NAME KMS_KEY_VERSION=KMS_KEY_VERSION
ここで
- KMS_KEY_PROJECT_ID は、鍵が格納されているプロジェクトの ID です。
- KMS_KEY_LOCATION は鍵の場所です。
- KMS_KEYRING_NAME はキーリングの名前です。
- KMS_KEY_NAME は鍵の名前です。
- KMS_KEY_VERSION は鍵バージョンです。
(省略可)KMS 鍵を設定します。
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
KMS キーリングを作成します。
gcloud kms keyrings create ${KMS_KEYRING_NAME} \ --location ${KMS_KEY_LOCATION} \ --project ${KMS_KEY_PROJECT_ID}
鍵を作成します。
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} \ --project ${KMS_KEY_PROJECT_ID}
KMS 鍵の作成の詳細については、非対称鍵の作成をご覧ください。
認証者に公開鍵を追加します。
gcloud --project="${ATTESTOR_PROJECT_ID}" \ alpha 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}"
ポリシーを構成する
これで、デプロイ担当者プロジェクトでポリシーを構成できます。この手順では、ポリシー 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/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME} name: projects/${DEPLOYER_PROJECT_ID}/policy EOM
ポリシー YAML ファイルを Binary Authorization にインポートします。
gcloud --project=${DEPLOYER_PROJECT_ID} \ beta container binauthz policy import /tmp/policy.yaml
ポリシーの構成の詳細については、CLI を使用したポリシーの構成をご覧ください。
ポリシーをテストする
上記で構成したポリシーをテストするには、サンプル コンテナ イメージをクラスタにデプロイします。必要な証明書が作成されていないため、ポリシーによってデプロイがブロックされます。
このチュートリアルでは、Container Registry のパス gcr.io/google-samples/hello-app
にあるサンプル イメージを使用できます。これは Google が作成した公開コンテナ イメージで、Hello, World! サンプル アプリケーションが含まれています。
イメージをデプロイするには:
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 "hello-server-579859fb5b-hjvnr" is forbidden: image policy webhook backend denied one or more images: Denied by default admission rule. Denied by Attestation Authority. Image gcr.io/google-samples/hello-app:1.0 denied by projects/example-project/attestors/test-attestor: No attestations found
デプロイを削除して次の手順に進みます。
kubectl delete deployment hello-server
証明書を作成する
証明書は、パイプラインで必要なプロセスが完了し、対象のコンテナ イメージのデプロイが承認されていることを証明するものです。証明書は、コンテナ イメージ レジストリに格納されているイメージのフルパスと認証者の ID を含むデジタル署名付きのレコードです。
このチュートリアルでは、イメージのデプロイが承認されていることのみを証明します。証明書プロジェクトで証明書を作成します。
証明書を作成するには:
イメージのレジストリパスとダイジェストを格納する変数を設定します。
IMAGE_PATH="gcr.io/google-samples/hello-app" IMAGE_DIGEST="sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea882eb722c3be4"
証明書ペイロードを生成します。
gcloud --project=${ATTESTATION_PROJECT_ID} \ beta container binauthz create-signature-payload \ --artifact-url=${IMAGE_PATH}@${IMAGE_DIGEST} > /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 ファイルを使用する場合は、ローカル PKIX 秘密鍵でペイロードに署名して署名ファイルを出力します。
openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
署名ファイルは、上記で作成したペイロード JSON ファイルのデジタル署名バージョンです。
Cloud KMS を使用している場合は、Cloud KMS サービスを使用してペイロードに署名します。
gcloud kms asymmetric-sign \ --location=${KMS_KEY_LOCATION} \ --keyring=${KMS_KEYRING_NAME} \ --key=${KMS_KEY_NAME} \ --version=${KMS_KEY_VERSION} \ --digest-algorithm=sha256 \ --input-file=/tmp/generated_payload.json \ --signature-file=/tmp/ec_signature \ --project ${KMS_KEY_PROJECT_ID}
認証者から公開鍵 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 ${ATTESTOR_PROJECT_ID})
証明するイメージの URL を作成します。
IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
証明書を作成します。
gcloud container binauthz attestations create \ --project="${ATTESTATION_PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --signature-file=/tmp/ec_signature \ --public-key-id="${PUBLIC_KEY_ID}"
または、次のように入力して、指定された認証者が証明書を検証できることを検証します。
gcloud alpha container binauthz attestations create \ --project="${ATTESTATION_PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --signature-file=/tmp/ec_signature \ --public-key-id="${PUBLIC_KEY_ID}" \ --validate
証明書が作成されたことを確認します。
gcloud --project=${ATTESTATION_PROJECT_ID} \ beta container binauthz attestations list \ --attestor=$ATTESTOR_NAME --attestor-project=$ATTESTOR_PROJECT_ID
証明書の作成の詳細については、証明書の作成をご覧ください。
ポリシーを再テストする
クラスタにサンプル コンテナ イメージをデプロイして、ポリシーを再度テストします。今回は、Binary Authorization はイメージパスとダイジェストの両方を使用して証明書を検索するため、1.0
や latest
などのタグではなく、ダイジェストを使用してイメージをデプロイする必要があります。ここでは、必要な証明書が作成されたため、Binary Authorization はイメージのデプロイを許可します。
イメージをデプロイするには:
kubectl run hello-server --image ${IMAGE_PATH}@${IMAGE_DIGEST} --port 8080
イメージがデプロイされたことを確認するには:
kubectl get pods
このコマンドを実行すると、デプロイが成功したことを示す次のようなメッセージが出力されます。
NAME READY STATUS RESTARTS AGE hello-server-579859fb5b-h2k8s 1/1 Running 0 1m
コンテナ イメージが正常にデプロイされ、設定が機能していることを確認したら、GKE で作成したクラスタを削除できます。
gcloud --project=${DEPLOYER_PROJECT_ID} \ container clusters delete \ --zone=us-central1-a \ test-cluster