本页面介绍了创建 Binary Authorization 证明的步骤。
您可以使用证明来授权要在 Google Kubernetes Engine (GKE) 和 Cloud Run 等平台上部署的特定容器映像。如需使用证明,您必须在政策的相应规则中要求提供证明。
单个证明可以授权存储在多个不同位置或不同注册表(例如 Artifact Registry、Container Registry 或外部容器注册表)中的相同映像。
在部署时,Binary Authorization 会使用证明者来验证证明。
如需在 Cloud Run、GKE、GKE 集群和 Cloud Service Mesh 上设置 Binary Authorization,请参阅按平台设置并选择您的平台。
GKE 用户:如需查看描述如何使用 Binary Authorization 和 Google Kubernetes Engine (GKE) 实现基于证明的强制执行的端到端教程,请参阅命令行工具使用入门或 Google Cloud 控制台使用入门。
准备工作
证明概览介绍了在创建证明之前需要完成的步骤。
设置环境
指定项目 ID:
ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
替换以下内容:
- ATTESTOR_PROJECT_ID:您要在其中存储证明者的项目的名称
- ATTESTATION_PROJECT_ID:您要在其中存储证明的项目的名称
如果您希望在证明者所在的项目中创建证明,请对这两个变量使用同一项目 ID。如需查看演示如何使用不同项目实现职责分离的端到端教程,请参阅多项目设置。
指定证明者名称和映像信息:
ATTESTOR_NAME=ATTESTOR_NAME IMAGE_PATH=IMAGE_PATH IMAGE_DIGEST=IMAGE_DIGEST IMAGE_TO_ATTEST="${IMAGE_PATH}@${IMAGE_DIGEST}"
替换以下内容:
- ATTESTOR_NAME:证明者的名称,例如
build-secure
或prod-qa
。 IMAGE_PATH:表示映像路径的 URI。虽然 URI 必须包含域名和映像名称,但它并不需要引用实际的映像。在创建证明期间,系统不会访问映像。下面是一些映像路径的示例:
us-docker.pkg.dev/google-samples/containers/gke/hello-app
gcr.io/example-project/quickstart-image
example.com/hello-app
。
IMAGE_DIGEST:映像清单的摘要。例如,
sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567
是与示例us-docker.pkg.dev/google-samples/containers/gke/hello-app
映像路径关联的映像摘要。如需了解如何在 Artifact Registry 中获取映像摘要,请参阅管理映像;如需查看 Container Registry 中的映像,请参阅列出映像版本。
- ATTESTOR_NAME:证明者的名称,例如
授予 Identity and Access Management 角色
如需创建证明,您必须将以下 Identity and Access Management (IAM) 角色授予给创建证明者的身份,如下所示:
- 与证明者关联的备注资源上的
roles/containeranalysis.notes.attacher
角色。 - 证明项目资源上的
roles/containeranalysis.occurrences.editor
角色。
您可以根据证明者创建证明。证明者与 Artifact Analysis 备注相关联。创建证明后,系统会创建一个 Artifact Analysis 发生实例并将其附加到备注。
详细了解如何授予访问权限。
如需了解如何在 Cloud Build 流水线中创建证明,请参阅使用 Kritis Signer 创建证明。
创建证明
创建使用本地存储密钥的证明
如需创建使用本地密钥签名的证明,请执行以下操作:
创建签名载荷文件:
gcloud
如需创建签名载荷文件,请输入以下命令:
gcloud container binauthz create-signature-payload \ --artifact-url="${IMAGE_TO_ATTEST}" > /tmp/generated_payload.json
JSON 格式的载荷文件类似于以下输出:
{ "critical": { "identity": { "docker-reference": "us-docker.pkg.dev/google-samples/containers/gke/hello-app" }, "image": { "docker-manifest-digest": "sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567" }, "type": "Google cloud binauthz container signature" } }
REST API
使用您在本文档前面部分设置的环境变量创建名为
/tmp/generated_payload.json
的载荷文件:cat > /tmp/generated_payload.json << EOM { "critical": { "identity": { "docker-reference": "${IMAGE_PATH}" }, "image": { "docker-manifest-digest": "${IMAGE_DIGEST}" }, "type": "Google cloud binauthz container signature" } } EOM
使用私钥对载荷签名以生成签名文件。
本指南使用推荐的椭圆曲线数字签名算法 (ECDSA) 算法进行签名。您还可以使用 RSA 算法。如需详细了解签名算法,请参阅密钥用途和算法。本指南还使用公钥基础架构 (X.509) (PKIX) 签名格式。您还可以使用 PGP。
PRIVATE_KEY_FILE=PRIVATE_KEY_FILE openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
将 PRIVATE_KEY_FILE 替换为您在创建证明者时生成的私钥的路径。
获取公钥 ID。
您可以通过输入以下命令从证明者中检索公钥 ID:
PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \ --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
创建证明:
gcloud
如需创建和验证证明,请输入以下命令:
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}" \ --validate
validate
标志用于检查证明是否可由您在政策中配置的证明者进行验证。注意:密钥 ID 可以是任何字符串。
REST API
如需创建证明,请执行以下操作:
检索与证明关联的证明者并提取存储的公钥 ID:
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
Binary Authorization 会返回类似于以下内容的 JSON 对象:
{ "name": "projects/example-project/attestors/test-attestor", "userOwnedGrafeasNote": { "noteReference": "projects/example-project/notes/test-attestor", "publicKeys": [ { "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70", "pkixPublicKey": { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n", "signatureAlgorithm": "ECDSA_P256_SHA256" } } ], "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com" }, "updateTime": "2019-06-26T16:58:33.977438Z" }
公钥可在
id
字段中找到。在
/tmp/attestation.json
中创建一个描述该证明的 JSON 文件:cat > /tmp/attestation.json << EOM { "resourceUri": "${IMAGE_TO_ATTEST}", "note_name": "${NOTE_URI}", "attestation": { "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)", "signatures": [ { "public_key_id": "${PUBLIC_KEY_ID}", "signature": "$(base64 --wrap=0 /tmp/ec_signature)" } ] } } EOM
创建证明:
curl -X POST \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ --data-binary @/tmp/attestation.json \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
使用 Cloud KMS 创建证明
如需使用 Cloud Key Management Service 创建证明,请执行以下操作:
创建环境变量:
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:在其中存储 Cloud Key Management Service 密钥的项目的 ID
- KMS_KEY_LOCATION:密钥的位置(默认为
global
) - KMS_KEYRING_NAME:密钥环的名称
- KMS_KEY_NAME:密钥的名称
- KMS_KEY_VERSION:密钥版本
对证明签名并创建证明:
gcloud
输入以下命令:
gcloud beta container binauthz attestations sign-and-create \ --project="${ATTESTATION_PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="${ATTESTOR_NAME}" \ --attestor-project="${ATTESTOR_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}"
REST API
使用您在上文中设置的环境变量创建名为
/tmp/generated_payload.json
的载荷文件:cat > /tmp/generated_payload.json << EOM { "critical": { "identity": { "docker-reference": "${IMAGE_PATH}" }, "image": { "docker-manifest-digest": "${IMAGE_DIGEST}" }, "type": "Google cloud binauthz container signature" } } EOM
对载荷文件签名:
curl \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $(gcloud auth print-access-token)" \ --header "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ --data '{"digest": {"DIGEST_ALGORITHM": "'$(openssl dgst -sha256 -binary /tmp/generated_payload.json | openssl base64)'" }}' \ https://cloudkms.googleapis.com/v1/projects/${KMS_KEY_PROJECT_ID}/locations/${KMS_KEY_LOCATION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME}/cryptoKeyVersions/${KMS_KEY_VERSION}:asymmetricSign?alt=json
将 DIGEST_ALGORITHM 替换为用于提取输入摘要的算法。本指南中的示例使用
sha256
摘要。您可以使用sha256
、sha384
或sha512
。在此示例中,输出类似于以下内容:
{ "signature": "<var>SIGNATURE</var>": "996305066", "name": "projects/<var>KMS_KEY_PROJECT_ID</var>/locations/<var>KMS_KEY_LOCATION</var>/keyRings/<var>KMS_KEYRING_NAME</var>/cryptoKeys/<var>KMS_KEY_NAME</var>/cryptoKeyVersions/<var>KMS_KEY_VERSION</var>" }
在此输出中,SIGNATURE 是载荷文件的 base64 编码签名。
将签名存储在环境变量中:
PAYLOAD_SIGNATURE=PAYLOAD_SIGNATURE
检索您要代表其对证明签名的证明者,并提取存储的公钥 ID 和备注 ID:
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
Binary Authorization 会返回类似于以下内容的 JSON 对象:
{ "name": "projects/example-project/attestors/test-attestor", "userOwnedGrafeasNote": { "noteReference": "projects/example-project/notes/test-attestor", "publicKeys": [ { "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70", "pkixPublicKey": { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n", "signatureAlgorithm": "ECDSA_P256_SHA256" } } ], "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com" }, "updateTime": "2019-06-26T16:58:33.977438Z" }
您可以在
id
和noteReference
字段中分别找到公钥 ID 和备注 ID。将公钥 ID 存储在环境变量中:
PUBLIC_KEY_ID="PUBLIC_KEY_ID" NOTE_URI="NOTE_URI"
替换以下内容:
- PUBLIC_KEY_ID:证明者的公钥 ID。
- NOTE_URI:与证明者关联的 Artifact Analysis 备注的 URI。
在
/tmp/attestation.json
中创建一个描述该证明的 JSON 文件:cat > /tmp/attestation.json << EOM { "resourceUri": "${IMAGE_TO_ATTEST}", "note_name": "${NOTE_URI}", "attestation": { "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)", "signatures": [ { "public_key_id": "${PUBLIC_KEY_ID}", "signature": "${PAYLOAD_SIGNATURE}" } ] } } EOM
创建证明:
curl -X POST \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ --data-binary @/tmp/attestation.json \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
您现已创建证明。
验证是否已创建证明
如需验证证明是否已创建,您可以列出与映像关联的证明。
gcloud
如需检索证明列表,请输入以下命令:
gcloud container binauthz attestations list\ --project="${ATTESTATION_PROJECT_ID}"\ --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}"\ --artifact-url="${IMAGE_TO_ATTEST}"
REST API
如需请求证明列表,请输入以下命令:
curl -X GET \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22
如果有很多证明,则响应可能包含 nextPageToken
值。在此情况下,您可以通过重复请求并添加 pageToken
查询参数来检索下一页结果,如下所示:
NEXT_PAGE_TOKEN=NEXT_PAGE_TOKEN curl -X GET \ -H "Content-Type: application/json" \ -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22&pageToken=${NEXT_PAGE_TOKEN}
将 NEXT_PAGE_TOKEN 替换为上一个请求响应中的 nextPageToken
值。
如果 nextPageToken
为空,表示没有更多结果。
删除证明
在删除证明之前,您应该执行以下操作:
了解删除该证明所产生的影响;删除证明最终会禁止部署与该证明关联的容器映像。
停止与您要删除的证明关联的所有正在运行的容器。
删除证明在所有可能位置中的所有副本,例如证明在 Artifact Registry 和 Artifact Analysis 代码库中的副本。
通过尝试重新部署,确保受影响的映像确实已被禁止部署。
如需删除证明,请执行以下命令:
列出证明:
gcloud container binauthz attestations list \ --attestor-project=${ATTESTOR_PROJECT_ID} \ --attestor=${ATTESTOR_NAME}
证明包含某个发生实例 ID。输出类似于以下内容:
projects/ATTESTOR_PROJECT_ID/occurrences/OCCURRENCE_ID
保存该发生实例 ID。
保存要删除的证明的发生实例 ID。
OCCURRENCE_ID=OCCURRENCE_ID
删除证明:
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" -X DELETE \ https://containeranalysis.googleapis.com/v1beta1/projects/${ATTESTATION_PROJECT_ID}/occurrences/${OCCURRENCE_ID}
再次列出证明,以验证证明是否已删除。
后续步骤
- 详细了解职责分离和 Identity and Access Management 角色分离。
- 在此多项目设置 (GKE) 教程中实现职责分离。
- 部署容器映像 (GKE) 到启用了 Binary Authorization 的集群。
- 部署容器映像 (Cloud Run) 到启用了 Binary Authorization 的集群。