產生及驗證建構來源資訊

本頁說明如何產生建構作業來源資訊、查看輸出內容及驗證。

建構作業來源資訊是一組可驗證的建構資料。來源中繼資料包含建構的映像檔摘要、輸入來源位置、建構引數和建構時長等詳細資料。您可以運用這項資訊,確保使用的建構構件準確可靠,且是由可信來源和建構人員所建立。

Cloud Build 支援根據 SLSA 0.11.0 版規格,產生符合軟體構件供應鏈級別 (SLSA) 第 3 級保證的建構作業來源資訊。

為支援 SLSA v1.0 規格,Cloud 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. 啟用 Cloud Build、容器分析和 Artifact Registry API。

    啟用 API 時所需的角色

    如要啟用 API,您需要服務使用情形管理員 IAM 角色 (roles/serviceusage.serviceUsageAdmin),其中包含 serviceusage.services.enable 權限。瞭解如何授予角色

    啟用 API

  2. 如要使用本指南提供的指令列範例,請安裝及設定 Google Cloud SDK

  3. 準備好原始碼。

  4. Artifact Registry 中建立存放區

產生建構作業來源資訊

下列操作說明介紹如何為儲存在 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. 在建構設定的 options 區段中,新增 requestedVerifyOption 選項並設為 VERIFIED 值。

    這項設定會啟用來源資訊產生功能,並將 Cloud Build 設為驗證來源資訊中繼資料是否存在。只有在產生出處時,建構作業才會標示為成功。

    YAML

    options:
      requestedVerifyOption: VERIFIED
    

    JSON

    {
        "options": {
            "requestedVerifyOption": "VERIFIED"
        }
    }
    
  3. 開始建構。

查看建構作業來源資訊

本節說明如何查看 Cloud Build 建立的建構作業來源資訊中繼資料。您可以擷取這項資訊以供稽核。

您可以使用 Google Cloud 控制台中的「安全性深入分析」側邊面板,或使用 gcloud CLI,存取容器的建構作業來源資訊中繼資料。

主控台

安全性深入分析側邊面板會顯示儲存在 Artifact Registry 中的構件安全性資訊總覽。

如要查看「安全性深入分析」面板,請按照下列步驟操作:

  1. 在 Google Cloud 控制台中開啟「建構記錄」頁面:

    開啟「建構記錄」頁面

  2. 在建構版本表格中,找出要查看安全性深入分析資訊的建構版本所在資料列。

  3. 在「安全性深入分析」欄下方,按一下「查看」

    這時畫面會顯示所選構件的「安全性深入分析」面板。

    「建構」資訊卡會顯示出處詳細資料和連結。按一下連結圖示,即可查看出處資訊片段。

如要進一步瞭解側邊面板,以及如何使用 Cloud 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:選用設定,可指定輸出格式

輸出範例

建構作業來源資訊類似如下:

      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 版出處資訊,輸出內容會使用以 Base64 編碼的 fileHash 欄位。

  • 簽章:如果您使用 SLSA 0.1 版出處,輸出內容的 envelope 欄位會包含兩個簽章。第一個簽章 (金鑰名稱為 provenanceSigner) 使用符合 DSSE 規範的簽章 (以預先驗證編碼 (PAE) 格式設定),可在二進位授權政策中驗證。建議您在出處的新用途中使用這個簽章。第二個簽章 (金鑰名稱為 builtByGCB) 適用於舊版用途。

  • 服務帳戶:Cloud Build 建構作業來源資訊中自動加入的簽章,可協助您驗證執行建構作業的建構服務。您也可以設定 Cloud Build,記錄用於啟動建構作業的服務帳戶相關可驗證中繼資料。詳情請參閱「使用 Cosign 簽署容器映像檔」。

  • 酬載:為方便閱讀,本頁面顯示的來源資訊範例已縮短。實際輸出內容會更長,因為酬載是所有出處中繼資料的 base-64 編碼版本。

  • 依附元件:您在建構檔案中指定的依附元件會納入出處資訊的 resolvedDependencies 欄位。

查看非容器構件的出處

將建構構件上傳至 Artifact Registry 時,Cloud Build 會為獨立的 Go、Java (Maven)、Python 和 Node.js (npm) 應用程式產生 SLSA 來源中繼資料。您可以直接呼叫 API,擷取出處中繼資料。

  1. 如要為構件產生來源資訊中繼資料,請使用 Cloud Build 執行建構作業。請參閱下列其中一個指南:

    建構作業完成後,請記下 BuildID

  2. 在終端機中執行下列 API 呼叫,即可擷取來源中繼資料,其中 PROJECT_ID 是與 Google Cloud 專案相關聯的 ID:

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

    您必須使用 API 呼叫,才能存取這類構件的出處中繼資料。非容器構件的來源中繼資料不會顯示在 Google Cloud 控制台中,也無法透過 gcloud CLI 存取。

  3. 在專案的發生次數中,按 BuildID 搜尋,找出與建構構件相關聯的出處資訊。

驗證來源

本節說明如何驗證容器映像檔的建構作業來源資訊。

驗證建構作業來源資訊可協助您:

  • 確認建構構件是從信任的來源和建構工具產生
  • 確保描述建構程序的出處中繼資料完整且真實

詳情請參閱「保護建構作業」。

使用 SLSA 驗證工具驗證出處

SLSA 驗證器是開放原始碼的 CLI 工具,可根據 SLSA 規格驗證建構完整性。

如果驗證器發現問題,會傳回詳細的錯誤訊息,協助您更新建構程序並降低風險。

如要使用 SLSA 驗證器,請按照下列步驟操作:

  1. slsa-verifier 存放區安裝 2.1 以上版本

    go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@VERSION
    
  2. 在 CLI 中,為圖片 ID 設定變數:

    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 驗證來源中繼資料

如要驗證建構作業來源資訊中繼資料是否遭到竄改,請按照下列步驟驗證來源資訊:

  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 | jq -r '.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. 上述指令參照了第一個出處簽章 (.provenance_summary.provenance[0].envelope.signatures[0]),該簽章是由 provenanceSigner 金鑰簽署。酬載會透過 PAE 格式的信封簽署。如要驗證,請執行下列指令,將出處轉換為預期的 PAE 格式 "DSSEv1" + SP + LEN(type) + SP + type + SP + LEN(body) + SP + body

    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

後續步驟