生成并验证 build 出处

本页介绍了如何生成 build 来源、查看输出并对其进行验证。

build 出处是关于 build 的可验证数据的集合。 出处元数据包括构建映像的摘要、 输入源位置、构建参数和构建时长。您可以 使用这些信息可确保您使用的已构建工件 准确可靠,由可靠信息来源和开发商制作。

Cloud Build 支持生成符合以下要求的构建出处: 软件制品的供应链级别 (SLSA) 3 级保证,基于 SLSA 版本 0.11.0

作为对 SLSA v1.0 规范的支持的一部分,Cloud Build 提供 build 出处中的 buildType 详细信息。您可以使用 buildType 架构 了解构建流程中使用的参数化模板,包括 Cloud Build 记录的值以及这些值的来源。 如需了解详情,请参阅 Cloud Build buildType v1

限制

  • Cloud Build 仅为存储的制品生成构建出处 (位于 Artifact Registry 中)。
  • 若要同时获得 SLSA v1.0 和 v0.1 出处,您必须使用 触发器。如果您使用 gcloud CLI,Cloud Build 仅提供 SLSA v0.1 出处。

准备工作

  1. Enable the Cloud Build, Container Analysis, and Artifact Registry APIs.

    Enable the APIs

  2. 要使用本指南中的命令行示例,请安装并配置 Google Cloud SDK

  3. 准备好源代码。

  4. 在 Artifact Registry 中拥有代码库

生成 build 出处

以下说明介绍了如何为以下各项生成构建出处: 存储在 Artifact Registry 中的容器映像:

  1. 在构建配置文件中,添加 images 字段以配置 Cloud Build 在构建完成后将构建的映像存储在 Artifact Registry 中。

    如果您使用显式 docker push 步骤将映像推送到 Artifact Registry,Cloud Build 将无法生成源代码。

    以下代码段显示了用于构建容器映像并将其存储在 Artifact Registry 中的 Docker 仓库中的构建配置:

    YAML

      steps:
      - name: 'gcr.io/cloud-builders/docker'
        args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE', '.' ]
      images: ['LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE']
    

    其中:

    • LOCATION:单区域或多区域位置 存储库
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • REPOSITORY:您的 Artifact Registry 代码库的名称。
    • IMAGE:容器映像的名称。

    JSON

      {
      "steps": [
          {
              "name": "gcr.io/cloud-builders/docker",
              "args": [
                  "build",
                  "-t",
                  "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE",
                  "."
              ]
          }
      ],
      "images": [
          "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE"
      ]
      }
    

    其中:

    • LOCATION:代码库的区域或多区域位置
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • REPOSITORY:您的 Artifact Registry 代码库的名称。
    • IMAGE:容器映像的名称。
  2. 在 build 配置的 options 部分中,添加 requestedVerifyOption 选项并将其值设置为 VERIFIED

    此设置启用出处生成功能,并配置 Cloud Build 验证是否存在出处元数据。build 只有在生成出处后才会被标记为成功。

    YAML

    options:
      requestedVerifyOption: VERIFIED
    

    JSON

    {
        "options": {
            "requestedVerifyOption": "VERIFIED"
        }
    }
    
  3. 开始构建。

查看构建来源

本部分介绍了如何查看由以下工具创建的构建来源元数据: Cloud Build您可以获取此信息以进行审核。

您可以使用 Google Cloud 控制台中的安全性数据分析侧边栏。 或使用 gcloud CLI

控制台

安全性数据分析侧边栏提供安全性的简要概览 Artifact Registry 中存储的工件的信息。

如需查看“安全性数据分析”面板,请执行以下操作:

  1. 在 Google Cloud 控制台中打开构建记录页面:

    打开“构建记录”页面

  2. 选择您的项目,然后点击打开

  3. 区域下拉菜单中,选择您在哪个区域运行了 build。

  4. 在包含 build 的表格中,找到您要查看安全数据洞见的 build 所在的行。

  5. 安全性数据分析列下,点击查看

    这会显示所选工件的安全性数据分析面板。

    构建卡片会显示出处详细信息和链接。您可以查看 来源代码段。

如需详细了解侧边栏以及如何使用 Cloud Build 有助于保护您的软件供应链,请参阅 查看 build 安全性数据分析

gcloud CLI

如需查看容器映像的出处元数据,请运行以下命令 命令:

  gcloud artifacts docker images describe \
  LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH \
  --show-provenance --format=FORMAT

替换以下内容:

  • LOCATION:以下各项的单区域或多区域位置 代码库
  • PROJECT_ID:您的 Google Cloud 项目 ID。
  • REPOSITORY:您的 Artifact Registry 的名称 存储库
  • IMAGE:容器映像的名称。
  • HASH:映像的 sha256 哈希值。您可以在构建的输出中找到此值。
  • FORMAT:一个可选设置,您可以在其中指定输出格式

输出示例

build 来源类似于以下内容:

      image_summary:
      digest: sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
      fully_qualified_digest: us-central1-docker.pkg.dev/my-project/my-repo/my-image@sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
      registry: us-central1-docker.pkg.dev
      repository: my-repo
      slsa_build_level: 0
    provenance_summary:
      provenance:
      - build:
          inTotoSlsaProvenanceV1:
            _type: https://in-toto.io/Statement/v1
            predicate:
              buildDefinition:
                buildType: https://cloud.google.com/build/gcb-buildtypes/google-worker/v1
                externalParameters:
                  buildConfigSource:
                    path: cloudbuild.yaml
                    ref: refs/heads/main
                    repository: git+https://github.com/my-username/my-git-repo
                  substitutions: {}
                internalParameters:
                  systemSubstitutions:
                    BRANCH_NAME: main
                    BUILD_ID: e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79
                    COMMIT_SHA: 525c52c501739e6df0609ed1f944c1bfd83224e7
                    LOCATION: us-west1
                    PROJECT_NUMBER: '265426041527'
                    REF_NAME: main
                    REPO_FULL_NAME: my-username/my-git-repo
                    REPO_NAME: my-git-repo
                    REVISION_ID: 525c52c501739e6df0609ed1f944c1bfd83224e7
                    SHORT_SHA: 525c52c
                    TRIGGER_BUILD_CONFIG_PATH: cloudbuild.yaml
                    TRIGGER_NAME: github-trigger-staging
                  triggerUri: projects/265426041527/locations/us-west1/triggers/a0d239a4-635e-4bd3-982b-d8b72d0b4bab
                resolvedDependencies:
                - digest:
                    gitCommit: 525c52c501739e6df0609ed1f944c1bfd83224e7
                  uri: git+https://github.com/my-username/my-git-repo@refs/heads/main
                - digest:
                    sha256: 154fcd4d2d65c6a35b06b98053a0829c581e223d530be5719326f5d85d680e8d
                  uri: gcr.io/cloud-builders/docker@sha256:154fcd4d2d65c6a35b06b98053a0829c581e223d530be5719326f5d85d680e8d
              runDetails:
                builder:
                  id: https://cloudbuild.googleapis.com/GoogleHostedWorker
                byproducts:
                - {}
                metadata:
                  finishedOn: '2023-08-01T19:57:10.734471Z'
                  invocationId: https://cloudbuild.googleapis.com/v1/projects/my-project/locations/us-west1/builds/e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79
                  startedOn: '2023-08-01T19:56:57.451553160Z'
            predicateType: https://slsa.dev/provenance/v1
            subject:
            - digest:
                sha256: 7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
              name: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image
            - digest:
                sha256: 7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
              name: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image:latest
        createTime: '2023-08-01T19:57:14.810489Z'
        envelope:
          payload:
          eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdMWQ0LWVjNGEtNGVhNi1hY2RkLWFjOGJiMTZkY2M3OSIsICJzdGFydGVkT24iOiIyMDIzLTA4LTAxVDE5OjU2OjU3LjQ1MTU1MzE2MFoiLCAiZmluaXNoZWRPbiI6IjIwMjMtMDgtMDFUMTk6NTc6MTAuNzM0NDcxWiJ9LCAiYnlwcm9kdWN0cyI6W3t9XX19fQ==...
          payloadType: application/vnd.in-toto+json
          signatures:
          - keyid: projects/verified-builder/locations/global/keyRings/attestor/cryptoKeys/google-hosted-worker/cryptoKeyVersions/1
            sig: MEUCIQCss8UlQL2feFePRJuKTE8VA73f85iqj4OJ9SvVPqTNwAIgYyuyuIrl1PxQC5B109thO24Y6NA4bTa0PJY34EHRSVE=
        kind: BUILD
        name: projects/my-project/occurrences/71787589-c6a6-4d6a-a030-9fd041e40468
        noteName: projects/argo-qa/notes/intoto_slsa_v1_e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79
        resourceUri: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image@sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
        updateTime: '2023-08-01T19:57:14.810489Z'
    

在此示例中,需要注意以下几点:

  • 来源构建是从 GitHub 代码库触发的

  • 对象参考:名为 digestfileHash 的字段引用 同一个对象。示例输出中包含的 digest 字段编码为 base 16(十六进制编码)。如果您使用的是 SLSA 0.1 版出处, 输出使用以 base 64 编码的 fileHash 字段。

  • 签名:如果您使用的是 SLSA 0.1 版出处,则您的输出 envelope 字段中包含两个签名。第一个 签名(其密钥名称为 provenanceSigner)使用 符合 DSSE 标准的签名 (格式为 预身份验证编码 (PAE)),可在 Binary Authorization 政策。我们建议您在此 API 的新用法中使用此签名 出处。第二个签名(密钥名称为 builtByGCB)供旧版使用。

  • 服务账号:自动包含在 Cloud Build 出处可帮助您验证 执行构建。您还可以将 Cloud Build 配置为 用于启动构建的服务账号的可验证元数据。 如需了解详情,请参阅使用协同签名为容器映像签名

  • 载荷:为方便阅读,本页上显示的来源示例已缩减。实际输出会更长,因为载荷是 base-64 格式 所有出处元数据的编码版本。

查看非容器制品的来源

当您将 build 工件上传到 Artifact Registry 时,Cloud Build 会为独立 Java (Maven)、Python 和 Node.js (npm) 应用生成 SLSA 来源元数据。您可以通过发出直接 API 调用来检索来源元数据。

  1. 如需为工件生成来源元数据,请使用 Cloud Build 运行构建。请使用以下指南之一:

    构建完成后,请注意 BuildID

  2. 通过在以下位置运行以下 API 调用来检索出处元数据: 终端,其中 PROJECT_ID 是与 您的 Google Cloud 项目:

    alias gcurl='curl -H"Authorization: Bearer $(gcloud auth print-access-token)"'
        gcurl 'https://containeranalysis.googleapis.com/v1/projects/PROJECT_ID/occurrences'
    

    您必须使用 API 调用来访问此类工件的来源元数据。未显示非容器制品的出处元数据 或通过 gcloud CLI 进行访问。

  3. 在项目的发生实例中,按 BuildID 搜索以查找 与构建工件相关联的出处信息。

验证出处

本部分介绍了如何验证容器映像的构建来源。

验证 build 出处有助于您:

  • 确认 build 工件是否由可信来源生成,并且 构建器
  • 确保描述构建流程的出处元数据是完整的 真实可信

如需了解详情,请参阅保护构建

使用 SLSA 验证器验证来源

SLSA 验证程序是一种开源 CLI 工具,可用于 根据 SLSA 规范验证 build 完整性。

如果验证程序发现问题,会返回详细的错误消息来帮助您 更新构建流程并降低风险

如需使用 SLSA 验证程序,请执行以下操作:

  1. slsa-verifier 代码库安装 2.1 版或更高版本:

    go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@VERSION
    
  2. 在 CLI 中,为映像标识符设置一个变量:

    export IMAGE=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH
    

    将命令中的占位值替换为以下内容:

    • LOCATION:单区域或多区域位置
    • PROJECT_ID:Google Cloud 项目 ID。
    • REPOSITORY:代码库名称。
    • IMAGE:映像名称。
    • HASH:映像的 sha256 哈希值。您可以在构建的输出中找到此值。
  3. 授权 gcloud CLI,以便 SLSA 验证程序可以访问您的出处数据:

    gcloud auth configure-docker LOCATION-docker.pkg.dev
    
  4. 检索映像的来源并将其存储为 JSON

    gcloud artifacts docker images describe $IMAGE --format json --show-provenance > provenance.json
    
  5. 验证来源:

    slsa-verifier verify-image "$IMAGE" \
    --provenance-path provenance.json \
    --source-uri SOURCE \
    --builder-id=BUILDER_ID
    

    其中:

    • SOURCE 是映像的源代码库 URI, 例如 github.com/my-repo/my-application
    • BUILDER_ID 是构建器的唯一 ID, 示例 https://cloudbuild.googleapis.com/GoogleHostedWorker

    如果要输出经过验证的出处,以便在政策引擎中使用,请使用带有 --print-provenance 标志的上一个命令。

    输出类似于以下内容:PASSED: Verified SLSA provenanceFAILED: SLSA verification failed: <error details>

如需详细了解可选标志,请参阅选项

使用 gcloud CLI 验证出处元数据

如果要验证 build 出处元数据是否未被篡改 则可通过执行以下步骤来验证出处:

  1. 创建一个新目录,并转到该目录。

    mkdir provenance && cd provenance
    
  2. 使用 keyid 字段中的信息获取公钥。

    gcloud kms keys versions get-public-key 1 --location global --keyring attestor \
      --key builtByGCB --project verified-builder --output-file my-key.pub
    
  3. payload 包含来源的 JSON 表示法,采用 base64url 编码。解码该数据并将其存储在一个文件中。

    gcloud artifacts docker images describe \
    LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
      --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v0.1") | .envelope.payload' | tr '\-_' '+/' | base64 -d > provenance.json
    

    SLSA 版本 0.1 和 1.0 的来源类型在可用时都会进行存储。如果 如果您要针对版本 1.0 进行过滤,请将 predicateType 更改为使用 https://slsa.dev/provenance/v1。例如:

    gcloud artifacts docker images describe \
    LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
      --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v1") | .envelope.payload' | tr '\-_' '+/' | base64 -d > provenance.json
    
  4. 信包还包含来源的签名。解码该数据并将其存储在一个文件中。

      gcloud artifacts docker images describe LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
      --format=json | '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v0.1") | .envelope.signatures[0].sig' | tr '\-_' '+/' | base64 -d > signature.bin
    

    如果您要针对版本 1.0 进行过滤,请将 predicateType 更改为使用 https://slsa.dev/provenance/v1。例如:

    gcloud artifacts docker images describe LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
    --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v1") | .envelope.signatures[0].sig' | tr '\-_' '+/' | base64 -d > signature.bin
    
  5. 上面的命令引用了由 provenanceSigner 密钥签名的第一个出处签名 (.provenance_summary.provenance[0].envelope.signatures[0])。载荷通过 PAE 格式的信封签名。为了验证这一点,请运行以下命令,将来源转换为预期的 "DSSEv1" + SP + LEN(type) + SP + type + SP + LEN(body) + SP + body PAE 格式。

    echo -n "DSSEv1 28 application/vnd.in-toto+json $(cat provenance.json | wc -c) $(cat provenance.json)" > provenance.json
    
  6. 验证签名。

    openssl dgst -sha256 -verify my-key.pub -signature signature.bin provenance.json
    

    验证成功后,输出为 Verified OK

后续步骤