產生及驗證建構來源資訊

本頁說明如何產生建構出處、查看輸出內容及驗證。

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

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 出處。
  • Docker 存放區附件 (包括建構出處) 不適用於清理政策。如果刪除圖片,系統也會一併刪除附加檔案。詳情請參閱「使用清除政策管理附件」。

事前準備

  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」(建構記錄) 頁面:

    開啟「建構記錄」頁面

  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 簽署容器映像檔」。

  • 酬載:為方便閱讀,本頁面顯示的來源資訊範例已縮短。實際輸出內容會更長,因為酬載是所有出處中繼資料的 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 格式的信封簽署。如要驗證,請執行這項指令,將出處轉換為預期的 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

後續步驟