This tutorial explains how to build Kritis Signer and use it to check container images for vulnerabilities before creating Binary Authorization attestations.
Overview
Kritis Signer is an open source command-line tool that can create Binary Authorization attestations based on a policy that you configure. You can also use Kritis Signer to create attestations after checking an image for vulnerabilities identified by Artifact Analysis.
Additionally, Cloud Build can run Kritis Signer as a custom builder in a build pipeline.
In this tutorial you perform a one-time build of the Kritis Signer custom builder, and then you run sample build pipelines. Each sample pipeline contains the following build steps:
- Build a sample container image.
- Push the image to Container Registry.
- Check and sign the image: Use Kritis Signer to create an attestation based on the policy.
In the check-and-sign build step of each pipeline, Kritis Signer does the following:
- Scans the newly built image with Artifact Analysis and retrieves a list of vulnerabilities.
- Checks the list of vulnerabilities against vulnerability signing rules in
the policy and then:
- If all of the identified vulnerabilities satisfy the vulnerability signing rules, Kritis Signer creates the attestation.
- If any of the identified vulnerabilities violate the vulnerability signing rules, Kritis Signer does not create the attestation.
At deploy time, the Binary Authorization enforcer checks for a verifiable attestation. Without one, the enforcer disallows the image from deploying.
This tutorial also explains how to run Kritis Signer in check-only mode in a Cloud Build pipeline. In this mode, Kritis Signer does not create an attestation, it only checks whether the vulnerability results satisfy the vulnerability signing rules in the policy. If they do, the Kritis Signer build step succeeds and the pipeline continues to run, otherwise the step fails and the pipeline exits.
Objectives
In this tutorial you do the following:
- Set up Kritis Signer as a Cloud Build custom builder.
- View a policy that contains vulnerability signing rules.
- Run Kritis Signer in create attestations based on vulnerability scanning results.
- Run Kritis Signer in check-only mode.
Costs
This tutorial uses the following Google Cloud products.
- Container Registry
- Artifact Analysis
- Cloud Build
- Cloud Key Management Service
Use the Pricing Calculator to generate a cost estimate based on your projected usage.
Before you begin
In this section, you perform a one-time setup of the system.
Set up your environment
Store your Google Cloud project in an environment variable.
export PROJECT_ID=PROJECT_ID
Replace PROJECT_ID with your Google Cloud project.
Set the default project ID to your Google Cloud project:
gcloud config set project $PROJECT_ID
Store the project number in an environment variable for future steps:
export PROJECT_NUMBER=$(gcloud projects list --filter="${PROJECT_ID}" \ --format="value(PROJECT_NUMBER)")
Enable APIs:
To ensure the services required for this guide are enabled, execute the following command:
gcloud services enable \ cloudbuild.googleapis.com \ containerregistry.googleapis.com \ containerscanning.googleapis.com \ cloudkms.googleapis.com
Set up IAM roles
Run the following commands to configure the Cloud Build service account with the following roles:
containeranalysis.notes.editor
: adds the Artifact Analysis Notes Editor role to manage the attestor.containeranalysis.notes.occurrences.viewer
: adds the Artifact Analysis Occurrences for Notes role to manage both the vulnerability and attestation occurrences.roles/containeranalysis.occurrences.editor
: adds the Artifact Analysis Occurrences Editor role to create attestation occurrences in Artifact Analysis.cloudkms.signer
: adds the Cloud KMS CryptoKey Signer role that allows the service account to access the Cloud KMS signing service.gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/containeranalysis.notes.editor gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/containeranalysis.notes.occurrences.viewer gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/containeranalysis.occurrences.editor gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/cloudkms.signer
Set up the Kritis Signer custom builder
In this section, you perform a one-time setup of the Kritis Signer custom builder. Once you obtain, build, and push Kritis Signer, it can then be used in any Cloud Build pipeline.
This section shows you how to:
- Clone the Kritis repository.
- Build the Kritis Signer Cloud Build custom builder.
- Push Kritis Signer to Container Registry to make it available for use as a Cloud Build build step.
Run the following commands to get the code and configuration files used in this guide:
Clone the Kritis repository:
git clone https://github.com/grafeas/kritis.git
This repository contains the following:
- Source code for Kritis that also includes Kritis Signer.
- A Cloud Build configuration file that is used by Cloud Build to build the Kritis Signer custom builder.
- An example policy that contains vulnerability signing rules.
- Example Cloud Build configuration files. Each configuration file uses Kritis Signer in a vulnerability scanning pipeline.
Navigate to the
kritis/
directory:cd kritis
Build and register Kritis Signer custom builder.
This one-time setup step builds the Kritis Signer custom builder and registers it with Cloud Build. Once registered, the custom builder is available for use in any Cloud Build pipeline.
gcloud builds submit . --config deploy/kritis-signer/cloudbuild.yaml
View an existing policy
This section shows an example Kritis Signer policy.
This policy configures Kritis Signer to request Artifact Analysis to scan the image for vulnerabilities. After the scan completes, Kritis Signer checks returned vulnerability results against the vulnerability signing rules in the policy.
You can edit the vulnerability signing rules in this policy to create an attestation based on the following:
- Severity levels of identified vulnerabilities.
- Specific vulnerabilities.
You can also set the policy to unconditionally create (ALLOW_ALL
) or not
create an (BLOCK_ALL
) an attestation.
To view the Kritis Signer policy, execute the following command:
cat samples/signer/policy-strict.yaml
The policy resembles the following:
Where:
maximumUnfixableSeverity
andmaximumFixableSeverity
define Common Vulnerabilities and Exposures (CVE) severity thresholds at which Kritis Signer creates attestations.maximumUnfixableSeverity
defines the threshold for severity for which a fix isn't currently available.maximumFixableSeverity
defines the threshold for severity for which a fix is currently available.maximumUnfixableSeverity
andmaximumFixableSeverity
can each be set to one of the following severity levels:CRITICAL
HIGH
MEDIUM
LOW
For more information on severity levels, see Severity levels.
Alternatively, you can set
maximumUnfixableSeverity
andmaximumFixableSeverity
to the following:BLOCK_ALL
: The attestation is not created if any vulnerability is identified.ALLOW_ALL
: The attestation is always created.
allowlistCVEs
is a list of specific CVEs to allowlist. Kritis Signer ignores CVEs in this list when evaluating whether to create an attestation. Each entry in the allowlist must exactly match the Artifact Analysis note name for the CVE. Learn more about Artifact Analysis Vulnerability sources. For more information about notes, see Metadata Storage.
Create a Cloud KMS signing key
Cloud Key Management Service keys are used to create the attestation.
Create a new Cloud KMS key ring with the name KEY_RING:
gcloud kms keyrings create KEY_RING \ --location global
Create a new Cloud KMS key called KEY_NAME within the key ring:
gcloud kms keys create KEY_NAME \ --keyring KEY_RING \ --location global \ --purpose "asymmetric-signing" \ --default-algorithm "rsa-sign-pkcs1-2048-sha256"
Store the digest algorithm and Cloud KMS in an environment variable for future steps:
export KMS_DIGEST_ALG=SHA256 export KMS_KEY_NAME=projects/$PROJECT_ID/locations/global/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions/1
Define a note name
All attestations reference a Artifact Analysis note. Kritis Signer automatically creates a note for a given name. You can also reuse existing note names.
export NOTE_ID=my-signer-note
export NOTE_NAME=projects/${PROJECT_ID}/notes/${NOTE_ID}
Create attestations with Kritis Signer in a Cloud Build pipeline
This section demonstrates how to use the Kritis Signer custom cloud builder to create Binary Authorization attestations based on vulnerability scanning results.
The following steps demonstrate how Kritis Signer works using the example build config files in the Kritis Signer repository. Each example config file contains the following build steps:
- A
docker build
step that builds a Docker container image. - A
docker push
step that pushes the newly built container image to Container Registry. A
vulnsign
step that checks and signs the container image by:- Waiting for Artifact Analysis to return vulnerability findings on the newly built container image.
- Checking the findings against the vulnerability signing rules in the policy.
- Creating the attestation if the findings satisfy the vulnerability rules.
You submit each of the example builds to Cloud Build. Each build produces a vulnerability result:
- Failure case: the vulnerability result violates the vulnerability signing rules. This build fails and no attestation is created.
- Success case: the vulnerability result satisfies the vulnerability signing rules. This build succeeds and an attestation is created.
Submit the failure-case sample build
In this section, you build a container image and scan it for vulnerabilities.
The build fails because the container image is based on a specific snapshot of
Debian 10, which contains a number of vulnerabilities with severity level
HIGH
. These vulnerabilities violate the vulnerability signing rule. As a
result, the builder doesn't produce an attestation.
(Optional) View the vulnerability signing policy file for the failure case.
cat samples/signer/policy-strict.yaml
Submit the build:
gcloud builds submit \ --substitutions=_KMS_KEY_NAME=$KMS_KEY_NAME,_KMS_DIGEST_ALG=$KMS_DIGEST_ALG,_NOTE_NAME=$NOTE_NAME \ --config=samples/signer/cloudbuild-bad.yaml samples/signer
You see output like the following:
"ERROR: (gcloud.builds.submit) build BUILD_ID completed with status "FAILURE"
Save the build ID from the last build:
export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
Verify the result:
gcloud storage cat gs://${PROJECT_NUMBER}.cloudbuild-logs.googleusercontent.com/log-${BUILD_ID}.txt | grep "does not pass VulnzSigningPolicy"
Submit the success-case sample build
In this section you build a container image that contains vulnerabilities that don't violate the vulnerability signing rules. In this case, the Kritis Signer custom builder creates an attestation.
To submit the success-case sample build to Cloud Build, do the following:
(Optional) View the vulnerability signing policy file for the success case.
cat samples/signer/policy-loose.yaml
Submit the build:
gcloud builds submit \ --substitutions=_KMS_KEY_NAME=$KMS_KEY_NAME,_KMS_DIGEST_ALG=$KMS_DIGEST_ALG,_NOTE_NAME=$NOTE_NAME \ --config=samples/signer/cloudbuild-good.yaml samples/signer
Save the build ID from the last build:
export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
Verify the result:
gcloud builds describe $BUILD_ID | grep status
Use Kritis Signer in check-only mode
This section shows you how to use Kritis Signer in check-only
mode. In this
mode, Kritis Signer does not create an attestation. It only checks the image
for vulnerabilities before either succeeding or failing the build step based on
the vulnerability signing rules.
Submit the failure-case sample build
(Optional) View the vulnerability signing policy file for the failure case.
cat samples/policy-check/policy-strict.yaml
In the Kritis Signer build step, note that the
mode
flag is set tocheck-only
.Submit the build:
gcloud builds submit \ --config=samples/policy-check/cloudbuild-bad.yaml samples/policy-check
Note that the build fails.
Save the build ID from the last build:
export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
Verify the result:
gcloud storage cat gs://${PROJECT_NUMBER}.cloudbuild-logs.googleusercontent.com/log-${BUILD_ID}.txt | grep "does not pass VulnzSigningPolicy"
Submit the success-case sample build
(Optional) View the vulnerability signing policy file for the success case.
cat samples/policy-check/policy-loose.yaml
Submit the build:
gcloud builds submit \ --config=samples/policy-check/cloudbuild-good.yaml samples/policy-check
Save the build ID from the last build:
export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
Verify the result:
gcloud builds describe $BUILD_ID | grep status
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.
Clean up
To clean up resources used in this document, you can delete the project:
gcloud projects delete ${PROJECT_ID}
What's next
- Kritis Signer documentation on GitHub
- Binary Authorization overview
- Create attestors through the Google Cloud console or the command-line tool
- Configure a policy to require attestations through the Google Cloud console or the command-line-tool
- Create attestations with Voucher
- Artifact Analysis and vulnerability scanning
- Cloud Build community and custom cloud builders