多项目设置

您可以在环境中通过单项目配置或多项目配置来设置 Binary Authorization。多项目配置适用于 Binary Authorization 的大多数实际应用,其中多个担任不同角色的人员可能负责软件供应链工作流的不同阶段。这通常称为职责分离。例如,这些角色可以是:

  • Deployer:根据公司政策将应用部署到 GKE 的单个流程或自动化流程。这部分工作的重点是部署软件。软件工程师或 DevOps 工程师通常会执行此操作。

  • Security Operations (SecOps) Manager:根据公司政策管理授权密钥的人员;Binary Authorization 会使用这些授权密钥强制执行需要证明的政策规则。此人员还可以创建政策、规则和证明者。这些证明者最终会验证证明,从而允许容器部署到 GKE。因此,只有此角色才能获取对证明者的写入权限。

  • Attestation Manager:创建和管理证明者要求的证明的人员。此人员负责生成和管理加密密钥。然后,他们会对容器映像描述符签名,以创建证明。然后,他们需要管理证明。

在本教程中,您将为上述每个角色设置不同的项目。您将为拥有 Deployer 角色的人员设置部署者项目,为拥有 Security Manager 角色的人员设置证明者项目,最后为拥有 Attestation Manager 角色的人员设置证明项目。

然后,您将使用要求提供证明的规则来配置 Binary Authorization 政策。最后,您将测试部署。

每个项目都会通过 Identity and Access Management (IAM) 进行适当的访问权限控制。

如需提升安全性,您可以使用 VPC Service Controls 进一步保护您在本教程中创建的资源。如需了解详情,请参阅使用 VPC Service Controls 进行保护

设置部署者项目

第一步是设置部署者项目。

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

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

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

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

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

    DEPLOYER_PROJECT_ID=PROJECT_ID
    

    其中,PROJECT_ID 是 Google Cloud 中相应项目的名称。

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

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

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

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

设置证明者项目

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

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

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

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

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

    ATTESTOR_PROJECT_ID=PROJECT_ID
    

    其中,PROJECT_ID 是 Google Cloud 中相应项目的名称。

    ATTESTOR_PROJECT_NUMBER=$(gcloud projects describe "${ATTESTOR_PROJECT_ID}" \
        --format="value(projectNumber)")
    
  4. 启用 Container 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"
    

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

设置证明项目

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

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

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

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

    ATTESTATION_PROJECT_ID=PROJECT_ID
    

    其中,PROJECT_ID 是 Google Cloud 中相应项目的名称。

  4. 启用 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 备注

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

    ATTESTOR_NAME=test-attestor
    NOTE_ID=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. 通过向 Container 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} \
        beta container binauthz attestors create ${ATTESTOR_NAME} \
        --attestation-authority-note=${NOTE_ID} \
        --attestation-authority-note-project=${ATTESTOR_PROJECT_ID}
    
  2. 验证证明者是否已创建:

    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 政策,向项目服务帐号分配 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}'
            ]
          }
        ]
      }
    }
    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(本地密钥)

    1. 生成私钥:

      PRIVATE_KEY_FILE 是包含用于对证明载荷签名的私钥的那个文件的名称。

      PRIVATE_KEY_FILE="/tmp/ec_private.pem"
      openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
      
    2. 从私钥中提取公钥并将其存储在一个文件中:

      PUBLIC_KEY_FILE 是包含要存储在证明者中的公钥的那个文件的名称。

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

      现在,将您导出的公钥添加到证明者中,供 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 中生成和存储的密钥执行证明。

    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}" \
          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 格式政策文件导出到本地系统,并修改默认规则,使其要求您在前面指定的证明者提供证明。

如需配置政策,请执行以下操作:

  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} \
        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

创建证明

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

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

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

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

    IMAGE_PATH="gcr.io/google-samples/hello-app"
    IMAGE_DIGEST="sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea882eb722c3be4"
    
  2. 生成证明载荷:

    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"
      }
    }
    
  3. 如果使用本地 PKIX 文件,请使用本地 PKIX 私钥对载荷签名并输出签名文件:

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

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

  4. 或者,如果您使用的是 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}
    
  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 ${ATTESTOR_PROJECT_ID})
    
  6. 为要证明的映像创建一个网址:

    IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
    
  7. 创建证明:

    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) 证明是否可以由提供的证明者进行验证,请运行以下命令:

    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
    
  8. 验证是否已创建证明:

    gcloud --project=${ATTESTATION_PROJECT_ID} \
        beta container binauthz attestations list \
        --attestor=$ATTESTOR_NAME --attestor-project=$ATTESTOR_PROJECT_ID
    

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

重新测试政策

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