Using On-Demand Scanning in your Cloud Build pipeline

Using On-Demand Scanning as part of your Cloud Build pipeline allows you to block builds if the container image has vulnerabilities with a severity matching a predefined level.

This tutorial shows you how to use Cloud Build to build your container image from the source code, scan it for vulnerabilities, check the severity levels of the vulnerabilities, and push the image to Artifact Registry if there are no vulnerabilities of a specific severity level.

You can use a similar approach to block a build if an existing built image has vulnerabilities that match the severity level.

Objectives

  • Build an image with Cloud Build.
  • Scan the built image with On-Demand Scanning.
  • Assess acceptable vulnerability levels.
  • Store the image in Artifact Registry.

Costs

This tutorial uses the following billable components of Google Cloud:

To generate a cost estimate based on your projected usage, use the pricing calculator. New Google Cloud users might be eligible for a free trial.

When you finish this tutorial, you can avoid continued billing by deleting the resources you created. For more information, see Clean up.

Before you begin

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud Console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Cloud project. Learn how to confirm that billing is enabled for your project.

  4. Enable the On-Demand Scanning, Cloud Build, and Artifact Registry APIs.

    Enable the APIs

  5. Install and initialize the Cloud SDK.
  6. In the Google Cloud Console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  7. Make sure that billing is enabled for your Cloud project. Learn how to confirm that billing is enabled for your project.

  8. Enable the On-Demand Scanning, Cloud Build, and Artifact Registry APIs.

    Enable the APIs

  9. Install and initialize the Cloud SDK.
  10. Grant the IAM role On-Demand Scanning Admin to your Cloud Build service account.

Prepare your source file

For this tutorial you are going to build an image from a Dockerfile. A Dockerfile is a source file that contains instructions for Docker to build an image.

  1. Open a terminal, create a new directory named ods-tutorial, and navigate to it:

    mkdir ods-tutorial && cd ods-tutorial
    
  2. Create a file named Dockerfile with the following contents:

    # Debian10 image
    FROM gcr.io/google-appengine/debian10:latest
    
    # Ensures that the built image is always unique
    RUN apt-get update && apt-get -y install uuid-runtime && uuidgen > /IAMUNIQUE
    

Create an Artifact Registry repository

  1. Set the project ID to the same project where you enabled the APIs:

    gcloud config set project PROJECT_ID
    
  2. Create a Docker repository named ods-build-repo in the location us-central1:

    gcloud artifacts repositories create ods-build-repo --repository-format=docker \
    --location=us-central1 --description="Repository for scan and build"
    
  3. Verify that your repository was successfully created:

    gcloud artifacts repositories list
    

Build your container

In this section you will run your build pipeline using a build config file. A build config file instructs Cloud Build how to perform several tasks based on your specifications.

  1. In the ods-tutorial/ folder, create the file cloudbuild.yaml with the following contents:

    steps:
       - id: build
         name: gcr.io/cloud-builders/docker
         entrypoint: /bin/bash
         args:
         - -c
         - |
           docker build -t us-central1-docker.pkg.dev/$_PROJECT_ID/ods-build-repo/ods-test:latest -f ./Dockerfile . &&
           docker image inspect us-central1-docker.pkg.dev/$_PROJECT_ID/ods-build-repo/ods-test:latest --format \
           '{{index .RepoTags 0}}@{{.Id}}' > /workspace/image-digest.txt &&
           cat image-digest.txt
       - id: scan
         name: gcr.io/cloud-builders/gcloud
         entrypoint: /bin/bash
         args:
         - -c
         - |
           gcloud artifacts docker images scan us-central1-docker.pkg.dev/$_PROJECT_ID/ods-build-repo/ods-test:latest \
           --format='value(response.scan)' > /workspace/scan_id.txt
       - id: severity check
         name: gcr.io/cloud-builders/gcloud
         entrypoint: /bin/bash
         args:
         - -c
         - |
           gcloud artifacts docker images list-vulnerabilities $(cat /workspace/scan_id.txt) \
           --format='value(vulnerability.effectiveSeverity)' | if grep -Fxq $_SEVERITY; \
           then echo 'Failed vulnerability check' && exit 1; else exit 0; fi
       - id: push
         name: gcr.io/cloud-builders/docker
         entrypoint: /bin/bash
         args:
         - -c
         - |
           docker push us-central1-docker.pkg.dev/$_PROJECT_ID/ods-build-repo/ods-test:latest
    images: ['us-central1-docker.pkg.dev/$_PROJECT_ID/ods-build-repo/ods-test:latest']
    
    
  2. Start the build:

    gcloud builds submit --substitutions=_PROJECT_ID=PROJECT_ID,_SEVERITY=SEVERITY \
    --config cloudbuild.yaml
    

    Where

    • PROJECT_ID is your project ID.
    • SEVERITY is the severity level for allowed vulnerabilities. If the image contains vulnerabilities of the given severity, the build fails. The possible values are:

      • CRITICAL
      • HIGH
      • MEDIUM
      • LOW
      • MINIMAL

      See the On-Demand Scanning severity levels section for more information.

If you set a CRITICAL severity level as the blocking level for this example, the build is successful since the image does not contain critical-level vulnerabilities. The image is be pushed to Artifact Registry. The output is similar to the following:

DONE
--------------------------------------------------------------------------------------------------------------------------------------------

ID                                    CREATE_TIME                DURATION  SOURCE                                                                                         IMAGES                                                                        STATUS
abb3ce73-6ae8-41d1-9080-7d74a7ecd7bc  2021-03-15T06:50:32+00:00  1M48S     gs://ods-tests_cloudbuild/source/1615791031.906807-a648d10faf4a46d695c163186a6208d5.tgz  us-central1-docker.pkg.dev/ods-tests/ods-build-repo/ods-test (+1 more)  SUCCESS

For a lower level, for example MEDIUM, the build fails and the output is similar to the following:

Step #2 - "severity check": Failed vulnerability check
Finished Step #2 - "severity check"
ERROR
ERROR: build step 2 "gcr.io/cloud-builders/gcloud" failed: step exited with non-zero status: 1

Clean up

To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.

Delete the project

  1. In the Cloud Console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Delete individual resources

Before you remove the repository, ensure that any images you want to keep are available in another location.

To delete the repository:

Console

  1. Open the Repositories page in the Cloud Console.

    Open the Repositories page

  2. In the repository list, select the ods-build-repo repository.

  3. Click Delete.

gcloud

To delete ods-build-repo the repository, run the following command:

gcloud artifacts repositories delete ods-build-repo --location=us-central1

What's next