Kritis Signer is a command-line tool that creates attestations for a container image. These attestations can be used for Kritis and Binary Authorization enforcement when you attempt to deploy the container image.
Kritis Signer can create attestations based on identified software vulnerabilities in your container images. To scan for vulnerabilities, your container image is uploaded to Google Container Registry where Google Container Analysis performs vulnerability scanning and produces a vulnerability result for the image. Kritis Signer then checks the vulnerability result against your vulnerability policy. If the vulnerability result complies with your policy, then Kritis Signer creates the attestation and stores it in the Container Analysis data store.
The tool can be run either locally or as part of a continuous integration (CI) pipeline. If you want to deploy the signer as a service, use the gcr-signer.
Support for other type of checks (e.g., base-image check), other vulnerability sources and attestation storage are underway.
This doc provides:
- a general overview;
- a step by step tutorial describing how to use the signer tool.
The tool can be run in three different modes:
- check-and-sign: default mode, checks policy conformance for a image, and conditionally creates attestation for the image if check passes. Currently, only vulnerability policy is supported.
- check-only: only checks policy conformance and outputs results, but does not create any attestation.
- bypass-and-sign: bypasses any check and creates attestation for a image.
mode | checking? | signing? |
---|---|---|
check-and-sign | ✓ | ✓ |
check-only | ✓ | |
bypass-and-sign | ✓ |
Users can specify the mode with -mode
flag.
Kritis Signer can check an image's metadata against rules in a user-provided policy. The tool now supports vulnerability-based policy check and will add more checks in the future.
During the checking process, the signer tool will fetch vulnerability results for the image from a vulnerability source. The tool now supports vulnerability scanning as a vulnerability source. If enabled, any image a user pushes to Google Container Registry, or gcr.io, will be automatically scanned for vulnerabilities.
The vulnerability signing policy is a YAML-formatted file. Kritis Signer uses the vulnerability signing policy you specify with the -policy
flag. Kritis Signer checks the vulnerability results from Container Analysis with the specified vulnerability policy to determine whether or not to create an attestation for the associated container image.
Field | Default (if applicable) | Description |
---|---|---|
packageVulnerabilityPolicy.maximumFixableSeverity | CRITICAL | Tolerance level for vulnerabilities found in the container image. |
packageVulnerabilityPolicy.maximumUnfixableSeverity | ALLOW_ALL | The tolerance level for vulnerabilities found that have no fix available. |
imageVulnerabilityRequirements.allowlistCVEs | List of CVEs which will be ignored, has to be full note name. |
Example policy:
apiVersion: kritis.grafeas.io/v1beta1
kind: VulnzSigningPolicy
metadata:
name: my-vsp
spec:
imageVulnerabilityRequirements:
maximumFixableSeverity: MEDIUM
maximumUnfixableSeverity: MEDIUM
allowlistCVEs:
- projects/goog-vulnz/notes/CVE-2020-10543
- projects/goog-vulnz/notes/CVE-2020-10878
- projects/goog-vulnz/notes/CVE-2020-14155
The valid severity levels are:
Value | Outcome |
---|---|
BLOCK_ALL | Block all vulnerabilities except listed in allowlist. |
LOW | Allow Containers with Low vulnerabilities. |
MEDIUM | Allow Containers with Low and Medium vulnerabilities. |
HIGH | Allow Containers with Low, Medium & High vulnerabilities. |
CRITICAL | Allow Containers with all known vulnerability levels (LOW to CRITICAL). |
ALLOW_ALL | Allow all vulnerabilities, including vulnerability with unknown severity levels. |
Signing is the process of creating and storing an attestation for an image. To create an attestation, you must first create a private signing key. Kritis Signer now supports PGP keys, PKIX keys, and also signing via Cloud KMS.
By default, Kritis Signer also uploads the attestation occurrence to Container Analysis. The uploaded attestation can be used by Binary Authorization and Kritis for deploy-time enforcement.
The tool supports three types of keys:
- PGP keys, using the
-pgp_private_key
flag, with the optional-pgp_passphrase
flag if your key is passphrase protected. - PKIX keys, using the
-pkix_private_key
and-pkix_alg
flags. Supported PKIX algorithms match those supported by Binary Authorization. - Cloud KMS, using the
-kms_key_name
and-kms_digest_alg
flags.
The tutorial walks you through how to run the signing helper tool in a local environment.
-
Build the tool.
go build -o ./signer ./cmd/kritis/signer
-
Enable GCP services.
The signing tool needs to access a number of Google Cloud Platform (GCP) services. First we need to pick a GCP project and enable those services within the project.
-
Set the default GCP project used by
gcloud
.export PROJECT_ID=[PROJECT ID]
-
Set the default GCP project used by
gcloud
.gcloud config set project ${PROJECT_ID}
-
Run
gcloud
to enable services within a project.gcloud services enable \ cloudbuild.googleapis.com \ containerregistry.googleapis.com \ containeranalysis.googleapis.com \ containerscanning.googleapis.com \ cloudkms.googleapis.com # If using Cloud KMS
-
-
Enable Google Cloud service accounts and Cloud IAM roles.
-
Create a service account within the GCP project.
export SA_NAME=[Service Account Name] gcloud iam service-accounts create ${SA_NAME}
-
Add roles to the created service account.
# permission to create note gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \ --role roles/containeranalysis.notes.editor # permission to view vulnerability and attestation occurrences gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \ --role roles/containeranalysis.notes.occurrences.viewer # permission to upload attestation occurrences gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \ --role roles/containeranalysis.occurrences.editor # (if using Cloud KMS) permission to cloud KMS signing service gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \ --role roles/cloudkms.signer
-
Create JSON credentials for the service account.
gcloud iam service-accounts keys create ./sa.json --iam-account ${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
The json credentials are saved in
sa.json
. -
Setting GAC environment variable.
export GOOGLE_APPLICATION_CREDENTIALS="$PWD/sa.json"
Now the signer tool will automatically pick up the credentials via the environment variable.
-
-
Creating a signing key.
A private signing key is required to create attestations for an image. In this example you use Cloud KMS with PKIX keys. Kritis Signer also supports PGP keys.
Run the following commands to create a key ring and an asymmetric signing key, and save the KMS key name.
gcloud kms keyrings create my-key-ring-1 \ --location global gcloud --project=$PROJECT_ID kms keys create my-signing-key-1 \ --keyring my-key-ring-1 \ --location global \ --purpose "asymmetric-signing" \ --default-algorithm "rsa-sign-pkcs1-2048-sha256"
Note down the digest algorithm “SHA256” and key name.
export KMS_DIGEST_ALG=SHA256 export KMS_KEY_NAME=projects/$PROJECT_ID/locations/global/keyRings/my-key-ring-1/cryptoKeys/my-signing-key-1/cryptoKeyVersions/1
-
Pick a note name.
All attestations need to be attached to a note. The signer tool will automatically create a note for a given name. It can also reuse an existing note.
export NOTE_ID=my-signer-note export NOTE_NAME=projects/${PROJECT_ID}/notes/${NOTE_ID}
-
Create vulnerability signing policy.
We have two example policies,
policy-strict.yaml
andpolicy-loose.yaml
. They differ in thatpolicy-loose.yaml
has higher severity thresholds.cat samples/signer/policy-strict.yaml apiVersion: kritis.grafeas.io/v1beta1 kind: VulnzSigningPolicy metadata: name: my-vsp spec: imageVulnerabilityRequirements: maximumFixableSeverity: MEDIUM maximumUnfixableSeverity: MEDIUM allowlistCVEs: - projects/goog-vulnz/notes/CVE-2020-10543 cat samples/signer/policy-loose.yaml apiVersion: kritis.grafeas.io/v1beta1 kind: VulnzSigningPolicy metadata: name: my-vsp spec: imageVulnerabilityRequirements: maximumFixableSeverity: CRITICAL maximumUnfixableSeverity: CRITICAL allowlistCVEs: - projects/goog-vulnz/notes/CVE-2020-10543
-
Run signer on a built image (pass example).
-
Build and push an example image.
docker build -t gcr.io/$PROJECT_ID/signer-test:example -f samples/signer/Dockerfile . docker push gcr.io/$PROJECT_ID/signer-test:example
-
Note down the image digest url.
export EXAMPLE_IMG_URL=$(docker image inspect gcr.io/$PROJECT_ID/signer-test:example --format '{{index .RepoDigests 0}}')
-
Run the signer with a loose policy.
./signer \ -v=10 \ -alsologtostderr \ -image=$EXAMPLE_IMG_URL \ -policy=samples/signer/policy-loose.yaml \ -kms_key_name=$KMS_KEY_NAME \ -kms_digest_alg=$KMS_DIGEST_ALG \ -note_name=$NOTE_NAME
The signer should output that the image "passes VulnzSigningPolicy my-vsp" and that an attestation is created and uploaded.
-
(optional) Run the tool in other modes.
The signer can also run in other modes to only perform policy check (
check-only
) or create attestation (bypass-and-sign
):./signer \ -mode=check-only \ -v=10 \ -alsologtostderr \ -image=$EXAMPLE_IMG_URL \ -policy=samples/signer/policy-loose.yaml \
./signer \ -mode=bypass-and-sign \ -v=10 \ -alsologtostderr \ -image=$EXAMPLE_IMG_URL \ -kms_key_name=$KMS_KEY_NAME \ -kms_digest_alg=$KMS_DIGEST_ALG \ -note_name=$NOTE_NAME
-
-
Run signer on a built image (fail example).
-
Build and push an example image (skippable if image from Step.7 is not deleted).
docker build -t gcr.io/$PROJECT_ID/signer-test:example -f samples/signer/Dockerfile . docker push gcr.io/$PROJECT_ID/signer-test:example
-
Note down the image digest url.
export EXAMPLE_IMG_URL=$(docker image inspect gcr.io/$PROJECT_ID/signer-test:example --format '{{index .RepoDigests 0}}')
-
Run the signer with a strict policy.
./signer \ -v=10 \ -alsologtostderr \ -image=$EXAMPLE_IMG_URL \ -policy=samples/signer/policy-strict.yaml \ -kms_key_name=$KMS_KEY_NAME \ -kms_digest_alg=$KMS_DIGEST_ALG \ -note_name=$NOTE_NAME
The signer should print out that the image "does not pass VulnzSigningPolicy my-vsp".
-
(optional) Run the tool in other modes.
The signer can also run in other modes to only perform policy check (
check-only
) or create attestation (bypass-and-sign
):./signer \ -mode=check-only \ -v=10 \ -alsologtostderr \ -image=$EXAMPLE_IMG_URL \ -policy=samples/signer/policy-strict.yaml \
./signer \ -mode=bypass-and-sign \ -v=10 \ -alsologtostderr \ -image=$EXAMPLE_IMG_URL \ -kms_key_name=$KMS_KEY_NAME \ -kms_digest_alg=$KMS_DIGEST_ALG \ -note_name=$NOTE_NAME
With
bypass-and-sign
mode, an attestation will still be created for the image.
-