配置一个多项目设置

本教程介绍如何在多项目配置中使用 Binary Authorization。如需了解更简单的单项目配置,请参阅 Google Cloud CLI 使用入门 (GKE)

如需实现职责分离,您可以在多项目配置中设置 Binary Authorization。本教程稍后将讨论每个项目的用途。

设置部署者项目

部署者项目负责管理要在其中部署映像的 Google Kubernetes Engine (GKE) 集群,以及 Binary Authorization 在部署时强制执行的 Binary Authorization 政策。您可以设置多个部署者项目,具体取决于环境的大小、复杂性和其他要求。

如需设置部署者项目,请执行以下操作:

  1. 在 Google Cloud 控制台中创建项目并启用结算功能(如果您尚未这样做)。

  2. Identity and Access Management 说明:部署者项目包含您的 GKE 集群。此项目的 Identity and Access Management 配置应反映这一点。

  3. 设置环境变量以存储 Google Cloud 项目和编号:

    DEPLOYER_PROJECT_ID=DEPLOYER_PROJECT_ID
    

    DEPLOYER_PROJECT_ID 替换为 Google Cloud 项目 ID。

    DEPLOYER_PROJECT_NUMBER=$(gcloud projects describe "${DEPLOYER_PROJECT_ID}" \
        --format="value(projectNumber)")
    
  4. 启用 API:

    Artifact Registry

    gcloud --project=${DEPLOYER_PROJECT_ID} \
      services enable\
      container.googleapis.com\
      artifactregistry.googleapis.com\
      binaryauthorization.googleapis.com
    
  5. 获取部署者项目服务账号名称:

    DEPLOYER_SERVICE_ACCOUNT="service-${DEPLOYER_PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
    

    在后续步骤中配置针对与证明者关联的 Artifact Analysis 备注的权限时,您可以使用该服务账号名称。

设置证明者项目

证明者项目会存储可验证映像是否可供部署的证明者通常,您的一个证明者项目可充当授权流程中可信方相关信息的集中存储区。这样,您就可以集中管理验证证明者身份所需的安全密钥,并仅允许这些密钥的管理方进行访问。

如需设置证明者项目,请执行以下操作:

  1. 在 Google Cloud 控制台中创建项目并启用结算功能(如果您尚未这样做)。

  2. Identity and Access Management 说明:由于此项目包含您的证明者,因此只有安全人员才应该拥有写入权限。

  3. 设置环境变量以存储项目 ID 和编号:

    ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID
    

    ATTESTOR_PROJECT_ID 替换为证明者项目 ID。

    ATTESTOR_PROJECT_NUMBER=$(gcloud projects describe "${ATTESTOR_PROJECT_ID}" \
        --format="value(projectNumber)")
    
  4. 启用 Artifact Analysis API 和 Binary Authorization API:

    gcloud services --project=${ATTESTOR_PROJECT_ID} \
        enable containeranalysis.googleapis.com \
        binaryauthorization.googleapis.com
    
  5. 获取证明者项目服务账号名称:

    ATTESTOR_SERVICE_ACCOUNT="service-${ATTESTOR_PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
    

    在后续步骤中配置针对与证明者关联的 Artifact Analysis 备注的权限时,您可以使用该服务账号名称。

设置证明项目

证明项目用于存储证明者在验证映像时所创建的证明通过单独的证明项目,您可以更轻松地整理和检查与软件就绪性有关的陈述。

  1. 在 Google Cloud 控制台中创建项目并启用结算功能(如果您尚未这样做)。

  2. Identity and Access Management 说明:Binary Authorization 中涉及的所有角色都应对此项目中的 Artifact Analysis 备注和发生实例拥有读取权限,但只有 Attestation Manager 需要拥有写入权限。

  3. 设置一个环境变量来存储项目名称:

    ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
    

    ATTESTATION_PROJECT_ID 替换为证明项目 ID。

  4. 启用 Artifact Analysis API 和 Binary Authorization API:

    gcloud services --project=${ATTESTATION_PROJECT_ID} \
        enable containeranalysis.googleapis.com \
        binaryauthorization.googleapis.com
    

创建集群

现在,您可以在部署者项目中创建 GKE 集群。这是您希望运行已部署的容器映像的集群。创建集群时,请将 --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE 标志传递给 gcloud container clusters create 命令。

如需创建集群,请运行以下命令:

gcloud --project=${DEPLOYER_PROJECT_ID} \
    container clusters create \
    --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
    --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) 流水线。您可以在证明者项目中创建证明者。

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

  • Artifact Analysis 中创建备注,以存储授权流程中使用的可信元数据
  • 在证明者项目中创建证明者本身,并关联您创建的备注
  • 向证明者添加部署者项目服务账号的 IAM 角色绑定
  • 设置针对 Artifact Analysis 备注的权限

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

创建 Artifact Analysis 备注

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

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

    您需要进行如下替换:

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

    cat > /tmp/note_payload.json << EOM
    {
      "name": "projects/${ATTESTOR_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/${ATTESTOR_PROJECT_ID}/notes/?noteId=${NOTE_ID}"
    
  4. 验证备注是否已创建:

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

创建证明者

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

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

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

    gcloud --project=${ATTESTOR_PROJECT_ID} \
        container binauthz attestors list
    

您创建的证明者在没有关联的 PKIX 密钥对(在下文中创建)的情况下尚无法使用。

添加部署者项目的 IAM 角色绑定

您必须向证明者添加部署者项目的 IAM 角色绑定。Binary Authorization 在评估政策以确定项目是否有权访问任何关联证明时,会用到此角色绑定。

如需添加 IAM 角色绑定,请执行以下操作:

gcloud --project ${ATTESTOR_PROJECT_ID} \
    container binauthz attestors add-iam-policy-binding \
    "projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \
    --member="serviceAccount:${DEPLOYER_SERVICE_ACCOUNT}" \
    --role=roles/binaryauthorization.attestorsVerifier

设置针对 Artifact Analysis 备注的权限

您还必须设置针对您创建的 Artifact Analysis 备注的权限,以便部署者项目和证明者项目都可以访问该备注。为此,您可以更新该备注的 IAM 政策,向项目服务账号分配 Viewer 访问权限。

  1. 生成一个 JSON 文件,其中包含针对您的备注设置 IAM 政策所需的信息。

    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}',
              'serviceAccount:${DEPLOYER_SERVICE_ACCOUNT}'
            ]
          }
        ]
      }
    }
    EOM
    
  2. 将服务账号和请求的访问角色添加到您创建的备注的 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 使用加密密钥来安全地验证证明者的身份。这样可以确保只有经过验证的各方才能参与容器映像的授权。密钥对由一个私钥(由证明者用于对证明进行数字签名)和一个公钥(您会将其添加到由 Binary Authorization 服务存储的证明者)组成。

在本教程中,您将使用推荐的椭圆曲线数字签名算法 (ECDSA) 创建密钥对。您也可以使用 RSA 或 PGP 密钥进行签名。如需详细了解如何对算法签名,请参阅密钥用途和算法

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

生成密钥对

PKIX 密钥对包含一个私钥(供签名者用于对证明进行数字签名)和一个公钥(您会将其添加到证明者)。在部署时,Binary Authorization 会使用此公钥来验证由私钥签名的证明。

  1. 生成私钥:

    如需生成新的本地非对称 PKIX 密钥对并将其存储在文件中,请执行以下操作:

    PKIX (Cloud KMS)

    此步骤介绍了如何使用在 Cloud Key Management Service 中生成和存储的密钥执行证明。

    1. 设置环境变量,以存储由 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:密钥版本
    2. [可选] 设置 KMS 密钥:

      1. 创建其公钥可存储在证明者中的 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
        
      2. 创建 KMS 密钥环:

        gcloud kms keyrings create ${KMS_KEYRING_NAME} \
          --location ${KMS_KEY_LOCATION} \
          --project ${KMS_KEY_PROJECT_ID}
        
      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} \
          --project ${KMS_KEY_PROJECT_ID}
        

        如需详细了解如何创建 KMS 密钥,请参阅创建非对称密钥

    3. 将公钥添加到证明者:

      gcloud --project="${ATTESTOR_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}"
      

    PKIX(本地密钥)

    1. 如需生成私钥,请运行以下命令:

      PRIVATE_KEY_FILE="/tmp/ec_private.pem"
      openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
      

      PRIVATE_KEY_FILE 是包含私钥的文件的名称,该私钥存储在证明者中。

    2. 从私钥中提取公钥并将其存储在一个文件中:

      PUBLIC_KEY_FILE="/tmp/ec_public.pem"
      openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
      

      PUBLIC_KEY_FILE 是包含公钥的文件的名称,该公钥存储在证明者中。

    3. 如需添加已导出到证明者的公钥,请运行以下代码。

      gcloud --project="${ATTESTOR_PROJECT_ID}" \
        container binauthz attestors public-keys add \
        --attestor="${ATTESTOR_NAME}" \
        --pkix-public-key-file=${PUBLIC_KEY_FILE} \
        --pkix-public-key-algorithm=ecdsa-p256-sha256
      

      Binary Authorization 使用证明者中的公钥来验证证明。

配置政策

现在,您可以在部署者项目中配置政策。在此步骤中,您将 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/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}
        name: projects/${DEPLOYER_PROJECT_ID}/policy
    EOM
    
  2. 将 YAML 格式政策文件导入 Binary Authorization:

    gcloud --project=${DEPLOYER_PROJECT_ID} \
        container binauthz policy import /tmp/policy.yaml
    

如需详细了解如何配置政策,请参阅使用 CLI 配置政策

测试政策

在本教程中,您将创建证明,例如 Artifact Registry 中的公开“Hello World!”映像。最初,强制执行程序会禁止部署映像,因为所需的证明不存在。

如需尝试部署映像,请运行以下命令:

Artifact Registry

kubectl run hello-server --image us-docker.pkg.dev/google-samples/containers/gke/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

创建证明

证明是证明者提供的表明流水线中的必需流程已完成且相关容器映像已获得部署授权的陈述。证明本身是一种经过数字签名的记录,其中包含指向容器映像注册表中存储的某版映像的完整路径以及证明者的身份。

在本教程中,您的证明仅说明您已授权对映像进行部署。您可以在证明项目中创建证明。

如需创建证明,请执行以下操作:

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

    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 --project=${ATTESTATION_PROJECT_ID} \
        container binauthz create-signature-payload \
        --artifact-url=${IMAGE_TO_ATTEST} > /tmp/generated_payload.json
      

      载荷 JSON 文件包含以下内容:

      Artifact Registry

      {
      "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"
      }
      }
      
    2. 对载荷签名。

      如果使用本地 PKIX 文件,请使用本地 PKIX 私钥对载荷签名并输出签名文件:

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

      输出文件是您在前面创建的载荷 JSON 文件的签名版本。

    3. 从证明者处获取公钥 ID。

      您可以随时使用如下命令查看您的公钥 ID:gcloud container binauthz attestors describe ATTESTOR_NAME

      如需将公钥 ID 保存到环境变量中,请输入以下命令:

      PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)' --project ${ATTESTOR_PROJECT_ID})
      
    4. 创建并验证证明:

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

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

    gcloud --project=${ATTESTATION_PROJECT_ID} \
        container binauthz attestations list \
        --attestor=$ATTESTOR_NAME --attestor-project=$ATTESTOR_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

现在,您已成功部署容器映像并验证设置是否有效,您可以通过以下命令删除在 GKE 中创建的集群了:

gcloud --project=${DEPLOYER_PROJECT_ID} \
    container clusters delete \
    --zone=us-central1-a \
    test-cluster