Securing image deployments to Cloud Run and Google Kubernetes Engine

This page provides instructions on how you can secure image deployments to Cloud Run and Google Kubernetes Engine using Cloud Build.

Learn how to configure Binary Authorization to check for build attestations and block deployments of images that are not generated by Cloud Build. This process can reduce the risk of deploying unauthorized software.

Before you begin

  1. Enable the Cloud Build, Binary Authorization, and Artifact Registry APIs.

    Enable the APIs

  2. To use the command-line examples in this guide, install and configure the Google Cloud SDK.

  3. Set up Binary Authorization for your platform.

Control deployments with Binary Authorization

A policy in Binary Authorization is a set of rules that govern the deployment of images. You can configure a rule to require digitally signed attestations.

Cloud Build generates and signs attestations at build time. With Binary Authorization you can use the built-by-cloud-build attestor to verify the attestations and only deploy images built by Cloud Build.

To create the built-by-cloud-build attestor in your project, run a build in that project.

To allow only images built by Cloud Build to be deployed, perform the following steps:

Console

  1. Go to the Binary Authorization page in the Google Cloud console.

    Go to Binary Authorization.

  2. In the Policy tab, click Edit Policy.

  3. In the Edit Policy dialog, select Allow only images that have been approved by all of the following attestors.

  4. Click Add Attestors.

  5. In the Add attestors dialog box, do the following:

    1. Select Add by project and attestor name and perform the following steps:
      1. In the Project name field, enter the project where you run Cloud Build.
      2. Click the Attestor name field and note that the built-by-cloud-build attestor is available.
      3. Click built-by-cloud-build.
    2. Alternatively, select Add by attestor resource ID. In Attestor resource ID, enter

      projects/PROJECT_ID/attestors/built-by-cloud-build
      

      Replacing PROJECT_ID with the project where you run Cloud Build.

  6. Click Add 1 attestor.

  7. Click Save Policy.

gcloud

  1. Export your existing policy to a file using the following command:

    gcloud container binauthz policy export > /tmp/policy.yaml
    
  2. Edit your policy file.

  3. Edit one of the following rules:

    • defaultAdmissionRule
    • clusterAdmissionRules
    • istioServiceIdentityAdmissionRules
    • kubernetesServiceAccountAdmissionRules
  4. Add a requireAttestationsBy block to the rule if there isn't one there already.

  5. In the requireAttestationsBy block, add

    projects/PROJECT_ID/attestors/built-by-cloud-build
    

    Replacing PROJECT_ID with the project where you run Cloud Build.

  6. Save the policy file.

  7. Import the policy file.

    gcloud container binauthz policy import /tmp/policy.yaml
    

    The following is an example policy file that contains the reference to the 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
    

    Replace PROJECT_ID with the project ID where you run Cloud Build.

You can view policy errors in the Binary Authorization log messages for GKE or Cloud Run

Using dry-run mode

In dry-run mode, Binary Authorization checks policy compliance without actually blocking the deployment. Instead, policy compliance status messages are logged to Cloud Logging. You can use these logs to determine if your blocking policy is working correctly and to identify false positives.

To enable dry run, do the following:

Console

  1. Go to the Binary Authorization page in the Google Cloud console.

    Go to Binary Authorization.

  2. Click Edit Policy.

  3. In Default Rule or a specific rule, select Dry-run mode.

  4. Click Save Policy.

gcloud

  1. Export the Binary Authorization policy to a YAML file:

    gcloud container binauthz policy export  > /tmp/policy.yaml
    
  2. In a text editor, set enforcementMode to DRYRUN_AUDIT_LOG_ONLY and save the file.

  3. To update the policy, import the file by executing the following command:

    gcloud container binauthz policy import /tmp/policy.yaml
    

You can view policy errors in the Binary Authorization log messages for GKE or Cloud Run

Limitations

  • Cloud Build and Binary Authorization must be in the same project. If you run your deployment platform in another project, refer to the Cloud Build project when adding the built-by-cloud-build attestor in Binary Authorization.

  • Cloud Build does not generate attestations when you push images to Artifact Registry using an explicit docker push build step. Make sure you push to Artifact Registry using the images field in your docker build build step. For more information on images, see Storing images in container registry.

  • You must use separate build config files for your build pipeline and deployment pipeline. This is because Cloud Build produces attestations only after the build pipeline completes successfully. Binary Authorization will then check the attestation before deploying the image.

Enable attestations in private pools

By default, Cloud Build does not generate Binary Authorization attestations for builds in private pools. To generate attestations, add the requestedVerifyOption: VERIFIED option to your build configuration file:

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

After adding the requestedVerifyOption, Cloud Build enables attestation generation and provenance metadata for your image.

View attestor metadata

An attestor is created the first time you run a build in a project. The attestor id is of the form projects/PROJECT_ID/attestors/built-by-cloud-build, where PROJECT_ID is your project ID.

You can check the build attestor metadata using the following command:

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

Replace PROJECT_ID with the project where you run Cloud Build.

The output contains information about the attestor and the corresponding public keys. For example:

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"

What's next