產生及驗證建構來源資訊

本頁面將說明如何產生建構來源、查看輸出內容並驗證。

版本來源是一組可驗證的版本資料。來源中繼資料包含詳細資料,例如已建構圖片的摘要、輸入來源位置、建構引數和建構時間長度。您可以利用這項資訊,確保您使用的已建構構件準確且可靠,且是由可信賴的來源和建構工具建立。

Cloud Build 支援產生符合「軟體構件供應鏈級別」(SLSA) 等級 3 保證的建構來源資訊,這項資訊必須符合 SLSA 版本 0.11.0 的規格。

為了支援 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. Enable the Cloud Build, Container Analysis, and Artifact Registry APIs.

    Enable the APIs

  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 控制台中開啟「Build History」頁面:

    開啟「Build History」(建構記錄) 頁面

  2. 選取您的專案並按一下 [Open] (開啟)

  3. 在「Region」下拉式選單中,選取您執行建構作業的區域。

  4. 在包含版本的資料表中,找出要查看安全性深入分析的版本列。

  5. 按一下「安全性深入分析」欄下方的「查看」

    系統會顯示所選構件「安全性深入分析」面板。

    「Build」資訊卡會顯示來源詳細資料和連結。只要按一下連結圖示,即可查看來源片段。

如要進一步瞭解側邊面板,以及如何使用 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 欄位是以 16 進制 (16 進位編碼) 編碼。如果您使用的是 SLSA 0.1 版來源,輸出內容會使用以 base64 編碼的 fileHash 欄位。

  • 簽名:如果您使用 SLSA 0.1 版來源,輸出內容會在 envelope 欄位中包含兩個簽名。第一個簽名 (具有金鑰名稱 provenanceSigner) 使用符合 DSSE 的簽名 (以預先驗證編碼 (PAE) 格式編寫),可在二進位授權政策中驗證。建議您在使用此來源時使用此簽章。第二個簽名 (名稱為 builtByGCB) 則提供給舊版使用者。

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

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

  • 依附元件:您在建構檔案中指定的依附元件會納入來源,並顯示在 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. 上述指令會參照由 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

後續步驟