署名付き来歴と Binary Authorization の使用

このページでは、Cloud Build でビルドの来歴メタデータを表示し、デプロイを制御する方法について説明します。

ビルドの来歴は、Cloud Build によって実行されたビルドに関する検証可能なデータのコレクションです。来歴のメタデータには、ビルドされたイメージのダイジェスト、入力ソースの場所、ビルド引数、ビルド時間などの詳細が含まれます。

ソフトウェアのサプライ チェーンを保護するために、Cloud Build は来歴のメタデータを記録し、ビルド時にコンテナ イメージの証明書を作成します。来歴メタデータは監査目的で使用でき、証明書を使用して Binary Authorization によってデプロイを制御できます。

制限事項

Cloud Build では、同じプロジェクトに Binary Authorization と Container Analysis のすべてのリソースが生成されます。Binary Authorization を構成するときにデプロイ プラットフォームを別のプロジェクトで実行している場合、built-by-cloud-build 認証者を追加する際にその Cloud Build プロジェクトを参照する必要があります。

始める前に

  • ビルドの来歴に関して生成されたメタデータを表示するには:

    Cloud Build, Container Analysis, and Artifact Registry API を有効にします。

    API を有効にする

  • Binary Authorization を使用してデプロイを制御し、認証者メタデータを表示するには、次のようにします。

    1. Cloud Build, Binary Authorization, and Artifact Registry API を有効にします。

      API を有効にする

    2. プラットフォームに Binary Authorization を設定します

ビルドの来歴を表示する

このセクションでは、Cloud Build によって作成されたビルドの来歴メタデータを表示する方法について説明します。

Cloud Build でイメージをビルドすると、イメージのビルド来歴は自動的に記録されます。この情報は監査目的で後で取得できます。来歴メタデータを生成するには、Cloud Build でビルドを実行します。

来歴メタデータを表示するには、次のコマンドを実行します。

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

コマンドのプレースホルダ値を、次のように置き換えます。

  • LOCATION: リージョンまたはマルチリージョンのロケーション
  • PROJECT_ID: Google Cloud プロジェクト ID
  • REPOSITORY: リポジトリの名前。
  • IMAGE: イメージの名前。
  • HASH: イメージの sha256 ハッシュ値。これはビルドの出力で確認できます。

出力は、SLSA 来歴の仕様で説明されているコンテナの来歴です。次に例を示します。

image_summary:
  digest: sha256:991ff3a4548c72e671070be2e86ff684fd0924f6b75ee60d25d85c8cdfde1293
  fully_qualified_digest: us-east1-docker.pkg.dev/PROJECT_ID/my-repo/my-image@sha256:991ff3a4548c72e671070be2e86ff684fd0924f6b75ee60d25d85c8cdfde1293
  registry: us-east1-docker.pkg.dev
  repository: my-repo
provenance_summary:
  provenance:
  - createTime: '2021-09-24T16:20:36.854156Z'
    dsseAttestation:
      envelope:
        payload: eyJfdHlwZS...
        payloadType: application/vnd.in-toto+json
        signatures:
        - keyid: projects/verified-builder/locations/global/keyRings/attestor/cryptoKeys/builtByGCB/cryptoKeyVersions/1
          sig: MEQCIHusA75t6LoyCngZ1_ACc-wWOlTThW6VKCyz75bnmSU0AiBYV50eFWQlDlp2cF-OV1u6j1_CtmrFdCNJCdyB6pYFsw==
      statement:
        predicateType: https://slsa.dev/provenance/v0.1
        provenance:
          builderConfig:
            id: https://cloudbuild.googleapis.com/Worker@v336731714
          metadata:
            buildFinishedOn: '2021-09-24T16:20:35.828284Z'
            buildInvocationId: c2f645df-f705-4aab-8d8f-ba2b1260f8ab
            buildStartedOn: '2021-09-24T16:20:23.224165401Z'
          recipe:
            arguments:
            - '@type': type.googleapis.com/google.devtools.cloudbuild.v1.BuildStep
              args:
              - build
              - --network
              - cloudbuild
              - --no-cache
              - -t
              - us-east1-docker.pkg.dev/PROJECT_ID/my-repo/my-image:tag1
              ....

メタデータが改ざんされていないことを確認するには、次の手順を行うことで来歴を検証できます。

  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 には、base64url でエンコードされた来歴の JSON 表現が含まれます。データをデコードしてファイルに保存します。

    gcloud artifacts docker images describe \
    LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
    --format=json | jq -r '.provenance_summary.provenance[0].dsseAttestation.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[0].dsseAttestation.envelope.signatures[0].sig' | tr '\-_' '+/' | base64 -d > signature.bin
    
  5. 署名を検証します。

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

    検証が成功すると、「Verified OK」が出力されます。

イメージに来歴のメタデータが関連付けられるように求める

Cloud Build で来歴メタデータが生成されていない場合でも、ビルドは正常に完了します。Cloud Build がイメージの来歴メタデータを生成しない場合に、デフォルトの動作を上書きしてビルドが失敗するようにするには、cloudbild.yaml ファイルに requestedVerifyOption: VERIFIED オプションを追加します。

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: [ 'build', '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/quickstart-docker-repo/quickstart-image:tag1', '.' ]
images:
- 'us-central1-docker.pkg.dev/$PROJECT_ID/quickstart-docker-repo/quickstart-image:tag1'
options:
  requestedVerifyOption: VERIFIED

requestedVerifyOption を追加した後、Cloud Build は、対応する来歴メタデータを生成できる場合にのみ、ビルドを成功としてマークします。これは、プライベート プールにビルドされたイメージにも影響し、これらのイメージで来歴メタデータと証明書の生成が有効になります。

Binary Authorization でデプロイを制御する

Binary Authorization ポリシーは、イメージのデプロイを制御する一連のルールです。ルールは、デジタル署名された証明書を要求するように構成できます。

Cloud Build は、ビルド時に証明書を生成して署名します。Binary Authorization では、built-by-cloud-build 認証者を使用して証明書を検証し、Cloud Build によってビルドされたイメージのみをデプロイできます。built-by-cloud-build 認証者は、プロジェクトで初めてビルドを実行するときに作成されます。

Cloud Build によってビルドされたイメージのみをデプロイできるようにするには、次の手順を行います。

Console

  1. Google Cloud Console で [Binary Authorization] ページに移動します。

    Binary Authorization に移動します

  2. [Policy](ポリシー)タブで [Edit Policy](ポリシーを編集)をクリックします。

  3. [ポリシーの編集] ダイアログで、[次のアテスターによって検証されたイメージのみを許可します] を選択します。

  4. [認証者の追加] をクリックします。

  5. [認証者の追加] ダイアログ ボックスで、次の操作を行います。

    1. [プロジェクトと認証者の名前により追加] を選択し、次の手順を行います。
      1. [プロジェクト名] フィールドに、Cloud Build を実行するプロジェクトを入力します。
      2. [認証者の名前] フィールドをクリックして、built-by-cloud-build 認証者が利用可能であることを確認します。
      3. [built-by-cloud-build] をクリックします。
    2. または、[認証者リソース ID により追加] を選択します。[認証者リソース ID] に「projects/PROJECT_ID/attestors/built-by-cloud-build」と入力します。PROJECT_ID は、Cloud Build を実行するプロジェクトに置き換えます。
  6. [Add 1 Attestor] をクリックします。

  7. [ポリシーを保存] をクリックします。

gcloud

  1. 次のコマンドを使用して、既存のポリシーをファイルにエクスポートします。

    gcloud container binauthz policy export > /tmp/policy.yaml
    
  2. ポリシー ファイルを編集します。

  3. 次のいずれかのルールを編集します。

    • defaultAdmissionRule
    • clusterAdmissionRules
    • istioServiceIdentityAdmissionRules
    • kubernetesServiceAccountAdmissionRules
  4. まだルールに requireAttestationsBy ブロックがない場合は、追加します。

  5. requireAttestationsBy ブロックで、projects/<var>PROJECT_ID</var>/attestors/built-by-cloud-build を追加します。PROJECT_ID は、Cloud Build を実行するプロジェクトに置き換えます。

  6. ポリシー ファイルを保存します。

  7. ポリシー ファイルをインポートします。

    gcloud container binauthz policy import /tmp/policy.yaml
    

    built-by-cloud-build-attestor への参照を含むポリシー ファイルの例を次に示します。

    defaultAdmissionRule:
      evaluationMode: REQUIRE_ATTESTATION
      enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
      requireAttestationsBy:
        - projects/PROJECT_ID/attestors/built-by-cloud-build
    name: projects/PROJECT_ID/policy
    

    PROJECT_ID は、Cloud Build を実行するプロジェクト ID に置き換えます。

ポリシーエラーは、GKE または Cloud Run の Binary Authorization ログメッセージで確認できます。

ドライラン モードを使用する

ドライラン モードでは、デプロイを実際にブロックすることなく、Binary Authorization でポリシーのコンプライアンスを確認します。なお、ポリシー遵守のステータス メッセージは、Cloud Logging に記録されます。これらのログを使用して、ブロッキング ポリシーが正常に動作しているかどうかを確認し、誤検出を特定できます。

ドライランを有効にするには、次の操作を行います。

Console

  1. Google Cloud Console で [Binary Authorization] ページに移動します。

    Binary Authorization に移動

  2. [ポリシーの編集] をクリックします。

  3. デフォルトのルールまたは固有のルールで、[ドライラン モード] を選択します。

  4. [ポリシーを保存] をクリックします。

gcloud

  1. Binary Authorization ポリシーを YAML ファイルにエクスポートします。

    gcloud container binauthz policy export  > /tmp/policy.yaml
    
  2. テキスト エディタで、enforcementModeDRYRUN_AUDIT_LOG_ONLY に設定し、ファイルを保存します。

  3. ポリシーを更新するには、次のコマンドを実行してファイルをインポートします。

    gcloud container binauthz policy import /tmp/policy.yaml
    

ポリシーエラーは、GKE または Cloud Run の Binary Authorization ログメッセージで確認できます。

認証者メタデータを確認する

認証者は、プロジェクトで初めてビルドを実行するときに作成されます。認証者 ID は、projects/PROJECT_ID/attestors/built-by-cloud-build です。ビルド認証者メタデータは、次のコマンドを使用して確認できます。

curl -X GET -H "Content-Type: application/json" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    https://binaryauthorization.googleapis.com/v1beta1/projects/PROJECT_ID/attestors/built-by-cloud-build

PROJECT_ID は、Cloud Build を実行するプロジェクトに置き換えます。

出力には、認証者と対応する公開鍵に関する情報が含まれます。次に例を示します。

name": "projects/PROJECT_ID/attestors/built-by-cloud-build",
  "userOwnedDrydockNote": {
    "noteReference": "projects/PROJECT_ID/notes/built-by-cloud-build",
    "publicKeys": [
      {
        "id": "//cloudkms.googleapis.com/v1/projects/verified-builder/locations/asia/keyRings/attestor/cryptoKeys/builtByGCB/cryptoKeyVersions/1",
        "pkixPublicKey": {
          "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMMvFxZLgIiWOLIXsaTkjTmOKcaK7\neIZrgpWHpHziTFGg8qyEI4S8O2/2wh1Eru7+sj0Sh1QxytN/KE5j3mTvYA==\n-----END PUBLIC KEY-----\n",
          "signatureAlgorithm": "ECDSA_P256_SHA256"
        }
      },
...
      }
    ],
    "delegationServiceAccountEmail": "service-942118413832@gcp-binaryauthorization.iam.gserviceaccount.com"
  },
  "updateTime": "2021-09-24T15:26:44.808914Z",
  "description": "Attestor autogenerated by build ID fab07092-30f4-4f70-caf7-4545cbc404d6"

次のステップ