This tutorial describes how to set up and use Voucher to create Binary Authorization attestations.
Overview of Voucher
Voucher is an open source tool that runs a suite of checks on container images before creating Binary Authorization attestations for the images. Voucher has a client and a server component. You run Voucher Client as an added step within your build pipeline, after the step that builds the image. When the Voucher Client build step runs, it submits the image to Voucher Server, which performs the checks. You define which checks Voucher runs, along with other criteria, in the Voucher Server configuration file.
This tutorial shows how to use the Voucher snakeoil
check to test for
vulnerabilities in images. You enable the check in the configuration file by
setting the fail-on
option to a vulnerability threshold, as shown later in
this tutorial.
After the snakeoil
check completes, if all of the identified vulnerabilities
fall below the threshold, Voucher Server creates the Binary Authorization
attestation for the image. If any of the identified vulnerabilities meet or
exceed the threshold, Voucher Server does not create an attestation.
At container image deploy time, without a verified attestation, the Binary Authorization enforcer disallows the image from being deployed.
Objectives
In this guide you do the following:
- Set up Voucher Server in Cloud Run.
- Set up Voucher Client.
- Use Voucher in example build pipelines.
Costs
This guide uses the following Google Cloud products.
- Container Registry
- Artifact Analysis
- Cloud Build
- Cloud Key Management Service
- Cloud Run
Use the Pricing Calculator to generate a cost estimate based on your projected usage.
Before you begin
- 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.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Build, Container Registry, Artifact Analysis, Cloud KMS, Cloud Run, and Identity and Access Management APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Build, Container Registry, Artifact Analysis, Cloud KMS, Cloud Run, and Identity and Access Management APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
- We recommend that you set up Binary Authorization with Google Kubernetes Engine. This tutorial describes how to create an attestation. In order to use deploy-time enforcement to verify the attestation and deploy the associated image, Binary Authorization must be set up. Make sure you configure the policy to require attestations. You can configure the policy in Google Cloud console or at the command line.
-
Specify your Google Cloud project in an environment variable.
export PROJECT_ID=PROJECT_ID
Replace PROJECT_ID with your project ID.
-
Set the project ID for
gcloud
commands:gcloud config set project ${PROJECT_ID}
-
Specify the project number in an environment variable for future steps:
export PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" \ --format='value(project_number)')
Set up Voucher Server
In the following steps you set up Voucher Server.
Create a Cloud Key Management Service signing key
In this section you create the key that Voucher Server uses to create a Binary Authorization attestation.
Create a key ring:
gcloud kms keyrings create KEY_RING\ --location global
Replace KEY_RING with a key ring name, such as
voucher-key-ring
.Create a signing key:
gcloud kms keys create KEY_NAME \ --keyring KEY_RING \ --location global \ --purpose "asymmetric-signing" \ --default-algorithm "rsa-sign-pkcs1-4096-sha512"
Replace KEY_NAME with the name a key name, such as
voucher-key
.Store the Cloud Key Management Service key version resource ID:
export KMS_RESOURCE_ID=projects/$PROJECT_ID/locations/global/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions/1
Grant the
cloudkms.signer
role to the Compute Engine runtime engine service account.In this step, you grant the
cloudkms.signer
role to the service account that runs Voucher Server. This enables Voucher Server to sign attestations with Cloud Key Management Service keys. To do this, execute the following command:gcloud kms keys add-iam-policy-binding\ KEY_NAME --keyring=KEY_RING\ --location=global\ --member=serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com\ --role=roles/cloudkms.signer
Create the Artifact Analysis note
In this section you create the note.
Store the note ID:
export NOTE_ID=snakeoil
Store the note URI:
export NOTE_URI=projects/$PROJECT_ID/notes/$NOTE_ID
Create request payload:
cat > /tmp/note_payload.json << EOM { "name": "${NOTE_URI}", "attestation": { "hint": { "human_readable_name": "voucher note for snakeoil check" } } } EOM
Create the note:
curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud --project ${PROJECT_ID} auth print-access-token)" \ -H "x-goog-user-project: ${PROJECT_ID}" \ --data-binary @/tmp/note_payload.json \ "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
Build and configure Voucher Server
In this one-time setup, you get, configure and build the Voucher Server image. You then store it in Container Registry.
Clone the Voucher repository:
git clone https://github.com/grafeas/voucher.git cd voucher/
This repository contains:
- Source code to build Voucher Server.
- Source code to build Voucher Client.
- Examples that demonstrate using Voucher.
Update the Voucher Server configuration file.
Linux
Create the Voucher Server configuration file from a template, replacing
and with values you defined above. You do this by executing the following command: cat tutorials/cloudrun/config.toml.template \ | sed -e "s?<PROJECT_ID>?${PROJECT_ID}?g" \ | sed -e "s?<KMS_KEY_NAME>?${KMS_RESOURCE_ID}?g" \ > tutorials/cloudrun/config.toml
Other OS
Edit the file
tutorials/cloudrun/config.toml.template
.- Replace
<PROJECT_ID>
with the value in${PROJECT_ID}
. - Replace
<KMS_KEY_NAME>
with the value in${KMS_RESOURCE_ID}
.
- Replace
Save the file as
tutorials/cloudrun/config.toml
.
View the Voucher Server configuration file:
cat tutorials/cloudrun/config.toml
You see output containing the following:
failon = "high"
Note that in the configuration file, the
failon
option is set tohigh
. This setting configures Voucher Server to perform a vulnerability check on an image. If the image contains vulnerabilities with severity ofHIGH
, the check fails and Voucher Server does not create the Binary Authorization attestation. For more information onfail-on
settings, see Fail-On: Failing on vulnerabilities.Build and upload the Voucher Server container image:
In this section you run the Cloud Build pipeline that builds the Voucher Server container image. The build also uploads the Voucher Server image to gcr.io/$PROJECT_ID/voucher-server.
gcloud builds submit --config ./tutorials/cloudrun/cloudbuild-server.yaml
Deploy Voucher Server on Cloud Run
Select a region.
To view a list of available regions, see Viewing a list of available regions. Create a variable to store your selected region:
export REGION=REGION
Replace REGION with the name of the region in which you plan to deploy your Voucher Server.
Deploy Voucher Server on Cloud Run.
gcloud run deploy --image gcr.io/${PROJECT_ID}/voucher-server \ --platform managed voucher-server \ --region ${REGION} \ --no-allow-unauthenticated
You see output like the following:
Service [voucher-server] revision [voucher-server-00001-caw] has been deployed and is serving 100 percent of traffic. Service URL: https://voucher-server-4wjtm2amga-uc.a.run.app
Store the Voucher Server service URL:
export SERVER_SERVICE_URL=$(gcloud run services describe voucher-server --platform managed --region ${REGION} --format='value(status.url)')
Set up Voucher Client
In the following steps you set up Voucher Client.
Create the invoker service account for Voucher Client:
gcloud iam service-accounts create INVOKER_ACCOUNT_NAME
Replace INVOKER_ACCOUNT_NAME with a name for the invoker service account, such as
voucher-invoker
.Specify the service account:
export INVOKER_SERVICE_ACCOUNT=INVOKER_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com
Grant the
run.invoker
role to the invoker service account for your project.Grant your invoker service account permission to invoke the Voucher Server on Cloud Run. To do this, enter the following command:
gcloud run services add-iam-policy-binding voucher-server \ --member serviceAccount:$INVOKER_SERVICE_ACCOUNT \ --role roles/run.invoker \ --platform managed \ --region ${REGION}
Grant the
iam.serviceAccountTokenCreator
role to the invoker service account for Cloud Build.In this section, you grant the Cloud Build service account permission to impersonate the invoker service account so that Voucher Client has permission to send requests to Voucher Server during the build. To do this, enter the following command:
gcloud iam service-accounts add-iam-policy-binding $INVOKER_SERVICE_ACCOUNT \ --member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \ --role=roles/iam.serviceAccountTokenCreator
Use Voucher to check images for vulnerabilities
In this section, you run two example Cloud Build pipelines. In both pipelines, you build an image and then use Voucher to check it for vulnerabilities.
Failure case
In this section the example build pipeline fails to create an attestation.
The image you build-based on Debian 9-contains at least one vulnerability
of severity HIGH
. The fail-on
option in the Voucher Server config.toml
is set to fail on HIGH
severity vulnerabilities. In this case,
Voucher Server does not create a Binary Authorization attestation.
Run the build pipeline:
gcloud builds submit \ --substitutions=_SERVICE_URL=$SERVER_SERVICE_URL,_SERVICE_ACCOUNT=$INVOKER_SERVICE_ACCOUNT \ --config=tutorials/cloudrun/examples/cloudbuild-bad.yaml tutorials/cloudrun/examples
Search the log from the last build for Voucher
snakeoil
findings:Console
Note the build ID from the last build.
In the Google Cloud console, go to the Build History page.
Under Build, click the item that contains the first few characters of the build ID.
Click View Raw.
Search for
snakeoil
using your browser.You see output like the following:
"name":"snakeoil","error":"vulnerable to 14 vulnerabilities"
gcloud
Save the build ID from the build:
export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
Search your build log by entering the following command:
gcloud builds log ${BUILD_ID} | grep "snakeoil"
The output looks like the following:
"name":"snakeoil","error":"vulnerable to 14 vulnerabilities"
Success case
In this section, the example build pipeline succeeds in creating an attestation.
All of the identified vulnerabilities are classified lower than the fail-on
threshold so the check passes the pipeline creates the attestation.
Run the pipeline:
gcloud builds submit\ --substitutions=_SERVICE_URL=$SERVER_SERVICE_URL,_SERVICE_ACCOUNT=$INVOKER_SERVICE_ACCOUNT\ --config=tutorials/cloudrun/examples/cloudbuild-good.yaml tutorials/cloudrun/examples
Search the log from the last build for Voucher
snakeoil
findings:Console
Note the build ID from the last build.
In the Google Cloud console, go to the Build History page.
Under Build, click the item that contains the first few characters of the build ID.
Click View Raw.
Search for
snakeoil
using your browser.You see output like the following:
"name":"snakeoil","success":true,"attested":true
gcloud
Save the build ID from the last build:
export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
Search your build log by entering the following command:
gcloud builds log ${BUILD_ID} | grep "snakeoil"
The output looks like the following:
"name":"snakeoil","success":true,"attested":true
Clean up
To clean up resources used in this document, you can delete the project as follows:
gcloud projects delete ${PROJECT_ID}
Create an attestor
To create a policy that requires the attestations that you create using the method described in this guide, you must first create an attestor.
To create an attestor, do the following:
Retrieve the public key material from the Cloud KMS key that you created earlier in this guide:
gcloud kms keys versions get-public-key 1 \ --key KEY_NAME \ --keyring KEY_RING \ --location global \ --output-file OUTPUT_PATH
KEY_NAME
: the key nameKEY_RING
: the key ring nameOUTPUT_PATH
: a file path—for example,my-key.pem
Create an attestor by using the public key material in the file and the note that you created earlier in this guide. You can create an attestor through the Google Cloud console or the gcloud CLI.
Create a policy that requires attestations and supply the attestor that you created in this section. You can create a policy through the Google Cloud console or the gcloud CLI
Create an attestation
To create an attestation using your attestor, see Create an attestation using Cloud KMS.
What's next
- Configure the Binary Authorization policy to require attestations using the command-line tool or Google Cloud console.
- Create the attestor Binary Authorization uses to verify the attestation at deploy time using the command-line tool or Google Cloud console.
- View Voucher documentation on GitHub.
- Learn about Binary Authorization.
- Learn about Artifact Analysis and vulnerability scanning.
- Learn about Cloud Key Management Service.