Google Cloud CLI 使用入门 (GKE)


本教程介绍了如何配置和测试要求提供证明的 Binary Authorization 政策。此类政策会在允许部署容器映像之前先验证该容器映像是否拥有已获签名的证明,从而保护基于容器的软件供应链的安全。

在部署时,Binary Authorization 使用证明者来验证证明中的数字签名。证明是由签名者创建的,它们通常是持续集成 (CI) 流水线的一部分。

在本教程中,GKE 集群、证明和证明者均位于单个项目中。单项目配置最适合用于测试或试用该服务。如需查看更多实际示例,请参阅多项目配置

以下步骤介绍了您可以通过命令行执行的任务。如需使用 Google Cloud 控制台执行这些步骤,请参阅 Google Cloud 控制台使用入门

目标

在本教程中,您将学习如何:

  • 创建启用了 Binary Authorization 的 Google Kubernetes Engine (GKE) 集群
  • 创建一个供 Binary Authorization Enforcer 用于验证证明中的签名的证明者
  • 配置要求提供证明的政策
  • 创建加密密钥对,用于对证明签名,并在稍后进行验证
  • 对容器映像摘要签名,同时创建签名
  • 使用签名创建证明
  • 通过将容器映像部署到 GKE 来测试政策

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. 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.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Install the Google Cloud CLI.
  5. To initialize the gcloud CLI, run the following command:

    gcloud init
  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  7. Make sure that billing is enabled for your Google Cloud project.

  8. Install the Google Cloud CLI.
  9. To initialize the gcloud CLI, run the following command:

    gcloud init
  10. 安装 kubectl,以与 GKE 进行交互。

启用 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 中的政策是一组规则,用于管理容器映像的部署。每个项目可以有一项政策。默认情况下,政策会配置为允许部署所有容器映像。

借助 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 Enforcer 用来在部署时决定是否允许 GKE 部署已签名的相应容器映像的验证机构。证明者包含公钥,通常由您的组织内负责软件供应链安全性的人员管理。

创建证明者需要您执行以下操作:

  • Artifact Analysis 中创建备注,以存储授权流程中使用的可信元数据
  • 在 Binary Authorization 中创建证明者本身,并将您创建的备注关联起来

在本教程中,您有一个名为 test-attestor 的证明者和一个名为 test-attestor-note 的 Container Analysis 备注。在实际使用场景中,您可以拥有任意数量的证明者,每个证明者代表参与容器映像授权过程的一方。

创建 Artifact Analysis 备注

  1. 设置变量,以存储证明者的名称和 Artifact Analysis 备注:

    ATTESTOR_NAME=test-attestor
    NOTE_ID=test-attestor-note
    

    您需要进行如下替换:

    • test-attestor:您选择的证明者名称。
    • attestor-note:您选择的证明者备注名称。
  2. /tmp/note_payload.json 中创建一个描述 Container Analysis 备注的 JSON 文件:

    cat > /tmp/note_payload.json << EOM
    {
      "name": "projects/${PROJECT_ID}/notes/${NOTE_ID}",
      "attestation": {
        "hint": {
          "human_readable_name": "Attestor Note"
        }
      }
    }
    EOM
    
  3. 通过向 Artifact Analysis REST API 发送 HTTP 请求来创建备注:

    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}"
    
  4. 验证备注是否已创建:

    curl \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
    

创建证明者

现在,您可以创建证明者:

  1. 在 Binary Authorization 中创建证明者:

    gcloud container binauthz attestors create ${ATTESTOR_NAME} \
    --attestation-authority-note=${NOTE_ID} \
    --attestation-authority-note-project=${PROJECT_ID}
    
  2. 验证证明者是否已创建:

    gcloud container binauthz attestors list
    

您创建的证明者在没有关联的密钥对(在本指南的后面部分中创建)的情况下尚无法使用。

生成密钥对

Binary Authorization 使用加密密钥来安全地验证签名者的身份。这样可以确保只能部署经过授权的容器映像。密钥对由私钥和公钥组成。签名者使用私钥对容器映像摘要签名,同时生成签名,然后签名会存储在证明中。公钥存储在证明者中。在部署时,Binary Authorization Enforcer 会使用证明者的公钥来验证证明中的签名,正确无误后才允许部署容器。

在本教程中,您需要为加密密钥使用公钥基础架构 (X.509) (PKIX) 格式。本教程使用推荐的椭圆曲线数字签名算法 (ECDSA) 来生成 PKIX 密钥对。您也可以使用 RSA 或 PGP 密钥对映像进行签名。

如需详细了解签名算法,请参阅密钥用途和算法

Cloud Key Management Service (Cloud KMS) 生成和存储的密钥符合 PKIX。如需详细了解如何使用 PKIX 密钥和 Cloud KMS,请参阅使用 gcloud CLI 创建证明者

PKIX (Cloud KMS)

如需在 Cloud KMS 中创建密钥对,请执行以下操作:

  1. 设置创建密钥对所需的环境变量。

    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
    
  2. 如需创建密钥环,请运行以下命令:

    gcloud kms keyrings create ${KMS_KEYRING_NAME} \
      --location ${KMS_KEY_LOCATION}
    
  3. 如需创建密钥,请运行以下命令:

    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}
    
  4. 如需将公钥添加到证明者,请运行以下命令:

    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}"
    
  5. 从证明者处获取公钥 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 密钥对,请按以下步骤操作:

  1. 创建私钥:

    PRIVATE_KEY_FILE="/tmp/ec_private.pem"
    openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
    
  2. 从私钥中提取公钥:

    PUBLIC_KEY_FILE="/tmp/ec_public.pem"
    openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
    
  3. 将公钥添加到证明者。

    现在,将您导出的公钥添加到证明者中,供 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
    
  4. 保存公钥 ID。

    如需保存公钥 ID,您可以从上面的 public-keys add 输出中进行复制。如需在将证明者的公钥添加到证明者后查看其 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 格式政策文件导出到本地系统,并修改默认规则,使其要求您在前面指定的证明者提供证明。

如需配置政策,请按照以下步骤操作:

  1. 创建一个新的政策文件,它应该允许 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
    
  2. 将 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。两个路径都包含由 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 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 Enforcer 会使用证明者的公钥来验证证明中的签名。

在本教程中,您的证明仅说明您已授权对映像进行部署。

如需创建证明,请按照下列步骤操作:

  1. 设置用于存储映像的注册表路径和摘要的变量:

    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}
    
  2. 如需创建证明,请执行以下操作:

    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(本地密钥)

    如需使用本地密钥创建证明,请执行以下操作:

    1. 生成证明载荷:

      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"
      }
      }
      
    2. 如需使用 PKIX 私钥对载荷签名并生成签名文件,请运行以下命令:

      openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
      

      签名文件是您在本指南前面部分中创建的载荷 JSON 文件的签名版本。

    3. 创建并验证证明:

      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 标志用于检查证明是否可由您在政策中配置的证明者进行验证。

  3. 验证是否已创建证明:

    gcloud container binauthz attestations list \
        --attestor=$ATTESTOR_NAME --attestor-project=$PROJECT_ID
    

如需详细了解如何创建证明,请参阅创建证明

重新测试政策

同样,可通过将示例容器映像部署到集群来测试政策。这次,您必须使用摘要(而非 1.0latest 等标记)部署映像,因为 Binary Authorization 将使用摘要来查找证明。在此,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

后续步骤