> [!WARNING]
>
> **Preview**
>
>
> This product or feature is
>
> subject to the "Pre-GA Offerings Terms" in the General Service Terms section
> of the [Service Specific
> Terms](https://docs.cloud.google.com/terms/service-terms#1).
>
> Pre-GA products and features are available "as is" and might have limited support.
>
> For more information, see the
> [launch stage descriptions](https://cloud.google.com/products/#product-launch-stages).

This page shows you how to use the Binary Authorization continuous validation (CV)
[Sigstore signature check](https://docs.cloud.google.com/binary-authorization/docs/overview-cv#sigstore-check).
The check verifies the Sigstore-generated signatures of container images
associated with Pods that run in a GKE clusters where CV is
enabled. The main difference between this check and the
[simple signing attestation check](https://docs.cloud.google.com/binary-authorization/docs/cv-attestation-check) is
that the Sigstore signing workflow does not use [Artifact Analysis notes](https://docs.cloud.google.com/binary-authorization/docs/key-concepts#analysis_notes)
to link signatures to images. All signatures are stored alongside the image
they sign.

This check supports only Artifact Registry repositories.

## Costs

This guide uses the following Google Cloud services:

- Binary Authorization, but CV is available free of charge during the [Preview](https://cloud.google.com/products/#product-launch-stages) stage
- GKE
- Cloud Key Management Service
- Artifact Registry

To generate a cost estimate based on your projected usage, use the
[pricing calculator](https://cloud.google.com/products/calculator).

## Before you begin

1. Ensure that the gcloud CLI is updated to the latest version.
2. [Install the `kubectl` command-line tool.](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl)
3. If your Binary Authorization policies and GKE clusters are in different projects, make sure that Binary Authorization is enabled in both projects.
4. [Install the `cosign` command-line tool.](https://docs.sigstore.dev/cosign/system_config/installation/)

## Required roles

This section shows you how to set roles for this check.

### Overview

If you run all of the products that are mentioned in this guide in the same
project, you don't need to set any permissions. Binary Authorization
configures the roles correctly when you enable it. If you run the products in
different projects, you must set roles as described in this section.


To ensure that the Binary Authorization Service Agent in each project has the necessary
permissions to evaluate the CV Sigstore signature check,

ask your administrator to grant the
following IAM roles to the Binary Authorization Service Agent in each project:

**Important:** You must grant these roles to the Binary Authorization Service Agent in each project, *not* to your user account. Failure to grant the roles to the correct principal might result in permission errors.

- If your cluster project is different from your policy project: [Binary Authorization Policy Evaluator](https://docs.cloud.google.com/iam/docs/roles-permissions/binaryauthorization#binaryauthorization.policyEvaluator) (`roles/binaryauthorization.policyEvaluator`) on the cluster project Binary Authorization Service Agent
- If your image repository project is different from your policy project: [Artifact Registry Reader](https://docs.cloud.google.com/iam/docs/roles-permissions/artifactregistry#artifactregistry.reader) (`roles/artifactregistry.reader`) on the policy project Binary Authorization Service Agent


For more information about granting roles, see [Manage access to projects, folders, and organizations](https://docs.cloud.google.com/iam/docs/granting-changing-revoking-access).


Your administrator might also be able to give the Binary Authorization Service Agent in each project
the required permissions through [custom
roles](https://docs.cloud.google.com/iam/docs/creating-custom-roles) or other [predefined
roles](https://docs.cloud.google.com/iam/docs/roles-overview#predefined).

### Grant roles using the gcloud CLI

To ensure that the Binary Authorization Service Agent in each project has the
necessary permissions to evaluate the CV Sigstore signature
check, grant the Binary Authorization Service Agent in each project the
following IAM roles:

1. Grant permission for the cluster project's Binary Authorization Service
   Agent to access the policy in the policy project.

   1. Get the cluster project's Binary Authorization service agent:

          PROJECT_NUMBER=$(gcloud projects list --filter="projectId:CLUSTER_PROJECT_ID" \
            --format="value(PROJECT_NUMBER)")
          CLUSTER_SERVICE_ACCOUNT="service-$PROJECT_NUMBER@gcp-sa-binaryauthorization.iam.gserviceaccount.com"

      Replace `CLUSTER_PROJECT_ID` with the project ID
      of the cluster.
   2. Allow CV to evaluate the policy on the cluster:

          gcloud projects add-iam-policy-binding POLICY_PROJECT_ID \
              --member="serviceAccount:$CLUSTER_SERVICE_ACCOUNT" \
              --role='roles/binaryauthorization.policyEvaluator'

      Replace `POLICY_PROJECT_ID` with the ID of the
      project that contains your policy.
2. Allow the policy project Binary Authorization Service Agent to access the
   signatures in your repository:

   1. Obtain the policy project's Binary Authorization service agent:

          PROJECT_NUMBER=$(gcloud projects list \
            --filter="projectId:POLICY_PROJECT_ID" \
            --format="value(PROJECT_NUMBER)")
          SERVICE_ACCOUNT="service-$PROJECT_NUMBER@gcp-sa-binaryauthorization.iam.gserviceaccount.com"

      Replace `POLICY_PROJECT_ID` with the ID of the
      project that contains your policy.
   2. Grant the role:

          gcloud projects add-iam-policy-binding REPOSITORY_PROJECT_ID \
              --member="serviceAccount:$SERVICE_ACCOUNT" \
              --role='roles/artifactregistry.reader'

      Replace `REPOSITORY_PROJECT_ID` with the ID of the
      project that contains your repository.

## Create a key pair

In this section, you create an [Elliptic Curve Digital Signature Algorithm (ECDSA)](https://docs.cloud.google.com/kms/docs/algorithms#asymmetric_signing_algorithms)
asymmetric key pair.

You use the private key to sign the image, which creates the attestation. You
include the public key in the platform policy. When CV checks the
attestation, it uses the public key to verify the attestation.

You can use either [Cloud Key Management Service (Cloud KMS)](https://docs.cloud.google.com/kms/docs/resource-hierarchy)
or local keys, but we recommend that you use Cloud KMS keys for production.

### PKIX Cloud KMS Cosign

1. Set up environment variables needed to create the key pair. To do so,
   we recommend that you fill in the placeholders in the following command,
   and then run the command.

       KMS_KEY_PROJECT_ID=KMS_KEY_PROJECT_ID
       KMS_KEYRING_NAME=KMS_KEYRING_NAME
       KMS_KEY_NAME=KMS_KEY_NAME
       KMS_KEY_LOCATION=global
       KMS_KEY_PURPOSE=asymmetric-signing
       KMS_KEY_ALGORITHM=ec-sign-p256-sha256
       KMS_PROTECTION_LEVEL=software
       KMS_KEY_VERSION=1

   Replace the following:
   - `KMS_KEY_PROJECT_ID`: your project ID
   - `KMS_KEYRING_NAME`: a name for your Cloud KMS key ring
   - `KMS_KEY_NAME`: a name for your Cloud KMS key
2. Generate the key with the Cosign CLI:

       cosign generate-key-pair \
         --kms gcpkms://projects/${KMS_KEY_PROJECT_ID}/locations/${KMS_KEY_LOCATION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME}

   > [!NOTE]
   > **Note:** You might have to run the command `gcloud auth application-default login` to correctly configure your credentials.

3. Record the location of the public key:

   Cosign automatically saves the generated public key as `cosign.pub` in the
   directory in which the `generate-key-pair` command was run. Save this file
   location in a variable for future commands.

       PUBLIC_KEY_FILE="$(pwd)/cosign.pub"

### PKIX Cloud KMS gcloud

To create the key pair in Cloud KMS, do the following:

1. Set up environment variables needed to create the key pair. To do so,
   we recommend that you fill in the placeholders in the following command,
   and then run the command.

       KMS_KEY_PROJECT_ID=KMS_KEY_PROJECT_ID
       KMS_KEYRING_NAME=KMS_KEYRING_NAME
       KMS_KEY_NAME=KMS_KEY_NAME
       KMS_KEY_LOCATION=global
       KMS_KEY_PURPOSE=asymmetric-signing
       KMS_KEY_ALGORITHM=ec-sign-p256-sha256
       KMS_PROTECTION_LEVEL=software
       KMS_KEY_VERSION=1

   Replace the following:
   - `KMS_KEY_PROJECT_ID`: your project ID
   - `KMS_KEYRING_NAME`: a name for your Cloud KMS key ring
   - `KMS_KEY_NAME`: a name for your Cloud KMS key
2. Create the key ring:

       gcloud kms keyrings create ${KMS_KEYRING_NAME} \
           --location=${KMS_KEY_LOCATION} \
           --project=${KMS_KEY_PROJECT_ID}

3. Create the key:

       gcloud kms keys create ${KMS_KEY_NAME} \
           --location=${KMS_KEY_LOCATION} \
           --keyring=${KMS_KEYRING_NAME}  \
           --purpose=${KMS_KEY_PURPOSE} \
           --default-algorithm=${KMS_KEY_ALGORITHM} \
           --protection-level=${KMS_PROTECTION_LEVEL} \
           --project=${KMS_KEY_PROJECT_ID}

4. Export the public key material to a file:

       PUBLIC_KEY_FILE="$(pwd)/cosign.pub"
       gcloud kms keys versions get-public-key 1 \
           --key=${KMS_KEY_NAME} \
           --keyring=${KMS_KEYRING_NAME} \
           --location=${KMS_KEY_LOCATION} \
           --output-file=${PUBLIC_KEY_FILE} \
           --project=${KMS_KEY_PROJECT_ID}

### Local key


> [!WARNING]
> **Warning:** We strongly recommend against using locally generated key pairs in production environments as they present a security risk. We recommend that you instead use Cloud Key Management Service. This example is provided for illustrative purposes only.

<br />

To create the key pair locally, do the following:

      cosign generate-key-pair
      PUBLIC_KEY_FILE="$(pwd)/cosign.pub"
      PRIVATE_KEY_FILE="$(pwd)/cosign.key"

## Create the platform policy

To create the CV platform policy with a Sigstore signature check,
do the following:

1. Create the Sigstore signature check platform policy file:

       cat > POLICY_PATH <<EOF
       gkePolicy:
         checkSets:
         - checks:
           - displayName: sigstore-signature-check
             sigstoreSignatureCheck:
               sigstoreAuthorities:
               - displayName: sigstore-authority
                 publicKeySet:
                   publicKeys:
                     publicKeyPem: |
       $(awk '{printf "                %s\n", $0}' ${PUBLIC_KEY_FILE})
       EOF

   Replace `POLICY_PATH` with the path to the policy file.
2. Create the platform policy:


   Before using any of the command data below,
   make the following replacements:
   - <var class="edit" scope="POLICY_ID" translate="no">POLICY_ID</var>: A platform policy ID of your choice. If the policy is in another project, you can use the full resource name: `projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID`.
   - <var class="edit" scope="POLICY_PATH" translate="no">POLICY_PATH</var>: A path to the policy file.
   - <var class="edit" scope="POLICY_PROJECT_ID" translate="no">POLICY_PROJECT_ID</var>: The policy project ID.


   Execute the

   following

   command:

   #### Linux, macOS, or Cloud Shell

   > [!NOTE]
   > **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

   ```bash
   gcloud beta container binauthz policy create POLICY_ID \
       --platform=gke \
       --policy-file=POLICY_PATH \
       --project=POLICY_PROJECT_ID
   ```

   #### Windows (PowerShell)

   > [!NOTE]
   > **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

   ```bash
   gcloud beta container binauthz policy create POLICY_ID `
       --platform=gke `
       --policy-file=POLICY_PATH `
       --project=POLICY_PROJECT_ID
   ```

   #### Windows (cmd.exe)

   > [!NOTE]
   > **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

   ```bash
   gcloud beta container binauthz policy create POLICY_ID ^
       --platform=gke ^
       --policy-file=POLICY_PATH ^
       --project=POLICY_PROJECT_ID
   ```

   <br />

## Enable CV


You can create a new cluster or update an existing cluster to use CV monitoring with check-based platform policies.

### Create a cluster that uses CV monitoring


In this section, you create a cluster that uses only CV
monitoring with check-based platform policies.


Before using any of the command data below,
make the following replacements:

- `CLUSTER_NAME`: a cluster name.
- `LOCATION`: the location---for example, `us-central1` or `asia-south1`.
- `POLICY_PROJECT_ID`: the ID of the project where the policy is stored.
- `POLICY_ID`: the policy ID.
- `CLUSTER_PROJECT_ID`: the cluster project ID.


Execute the

following

command:

#### Linux, macOS, or Cloud Shell

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters create CLUSTER_NAME \
    --location=LOCATION \
    --binauthz-evaluation-mode=POLICY_BINDINGS \
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID \
    --project=CLUSTER_PROJECT_ID
```

#### Windows (PowerShell)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters create CLUSTER_NAME `
    --location=LOCATION `
    --binauthz-evaluation-mode=POLICY_BINDINGS `
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID `
    --project=CLUSTER_PROJECT_ID
```

#### Windows (cmd.exe)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters create CLUSTER_NAME ^
    --location=LOCATION ^
    --binauthz-evaluation-mode=POLICY_BINDINGS ^
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID ^
    --project=CLUSTER_PROJECT_ID
```

### Create cluster that uses enforcement and CV monitoring


In this section, you create a cluster that uses both
[project-singleton](https://docs.cloud.google.com/binary-authorization/docs/key-concepts#project-singleton-policy) policy enforcement and CV monitoring with check-based platform policies:


Before using any of the command data below,
make the following replacements:

- `CLUSTER_NAME`: a cluster name.
- `LOCATION`: the location---for example, `us-central1` or `asia-south1`.
- `POLICY_PROJECT_ID`: the ID of the project where the policy is stored.
- `POLICY_ID`: the policy ID.
- `CLUSTER_PROJECT_ID`: the cluster project ID.


Execute the

following

command:

#### Linux, macOS, or Cloud Shell

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters create CLUSTER_NAME \
    --location=LOCATION \
    --binauthz-evaluation-mode=POLICY_BINDINGS_AND_PROJECT_SINGLETON_POLICY_ENFORCE \
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID \
    --project=CLUSTER_PROJECT_ID
```

#### Windows (PowerShell)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters create CLUSTER_NAME `
    --location=LOCATION `
    --binauthz-evaluation-mode=POLICY_BINDINGS_AND_PROJECT_SINGLETON_POLICY_ENFORCE `
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID `
    --project=CLUSTER_PROJECT_ID
```

#### Windows (cmd.exe)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters create CLUSTER_NAME ^
    --location=LOCATION ^
    --binauthz-evaluation-mode=POLICY_BINDINGS_AND_PROJECT_SINGLETON_POLICY_ENFORCE ^
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID ^
    --project=CLUSTER_PROJECT_ID
```

### Update a cluster to use CV monitoring


In this section, you update a cluster to use CV monitoring
with check-based platform policies only. If the cluster already has
project-singleton policy enforcement enabled, running this command disables
it. Instead, consider updating the cluster with enforcement and
CV monitoring enabled.


Before using any of the command data below,
make the following replacements:

- `CLUSTER_NAME`: the cluster name
- `LOCATION`: the location---for example: `us-central1` or `asia-south1`
- `POLICY_PROJECT_ID`: the ID of the project where the policy is stored
- `POLICY_ID`: the policy ID
- `CLUSTER_PROJECT_ID`: the cluster project ID


Execute the

following

command:

#### Linux, macOS, or Cloud Shell

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --binauthz-evaluation-mode=POLICY_BINDINGS \
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID \
    --project=CLUSTER_PROJECT_ID
```

#### Windows (PowerShell)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters update CLUSTER_NAME `
    --location=LOCATION `
    --binauthz-evaluation-mode=POLICY_BINDINGS `
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID `
    --project=CLUSTER_PROJECT_ID
```

#### Windows (cmd.exe)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters update CLUSTER_NAME ^
    --location=LOCATION ^
    --binauthz-evaluation-mode=POLICY_BINDINGS ^
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID ^
    --project=CLUSTER_PROJECT_ID
```

### Update a cluster to use enforcement and CV monitoring


In this section, you update a cluster to use both project-singleton policy
enforcement and CV monitoring with check-based platform
policies.


Before using any of the command data below,
make the following replacements:

- `CLUSTER_NAME`: a cluster name
- `LOCATION`: the location---for example: `us-central1` or `asia-south1`
- `POLICY_PROJECT_ID`: the ID of the project where the policy is stored
- `POLICY_ID`: the policy ID
- `CLUSTER_PROJECT_ID`: the cluster project ID


Execute the

following

command:

#### Linux, macOS, or Cloud Shell

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --binauthz-evaluation-mode=POLICY_BINDINGS_AND_PROJECT_SINGLETON_POLICY_ENFORCE \
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID \
    --project=CLUSTER_PROJECT_ID
```

#### Windows (PowerShell)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters update CLUSTER_NAME `
    --location=LOCATION `
    --binauthz-evaluation-mode=POLICY_BINDINGS_AND_PROJECT_SINGLETON_POLICY_ENFORCE `
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID `
    --project=CLUSTER_PROJECT_ID
```

#### Windows (cmd.exe)

> [!NOTE]
> **Note:** Ensure you have initialized the Google Cloud CLI with authentication and a project by running either [gcloud init](https://docs.cloud.google.com/sdk/gcloud/reference/init); or [gcloud auth login](https://docs.cloud.google.com/sdk/gcloud/reference/auth/login) and [gcloud config set project](https://docs.cloud.google.com/sdk/gcloud/reference/config/set).

```bash
gcloud beta container clusters update CLUSTER_NAME ^
    --location=LOCATION ^
    --binauthz-evaluation-mode=POLICY_BINDINGS_AND_PROJECT_SINGLETON_POLICY_ENFORCE ^
    --binauthz-policy-bindings=name=projects/POLICY_PROJECT_ID/platforms/gke/policies/POLICY_ID ^
    --project=CLUSTER_PROJECT_ID
```

## Test CV

In this section, you test CV by deploying a signed image. In this
case, the CV Sigstore signature check verifies the signature and
produces no log entry.

You then attempt to deploy a different unsigned image. In this case, the
CV check can't find a valid signature and logs the violation to
Cloud Logging.

### Sign an image

To satisfy the check the image needs a valid signature. To create the
signature, do the following:

1. Create the variables you use to sign the image:

       IMAGE_PATH=IMAGE_PATH
       IMAGE_DIGEST=sha256:IMAGE_DIGEST_SHA
       IMAGE_TO_SIGN="${IMAGE_PATH}@${IMAGE_DIGEST}"

   Replace the following:
   - `IMAGE_PATH`: the path to your image
   - `IMAGE_DIGEST_SHA`: the SHA hash of the your image's digest
2. Sign the image and push the signature to Artifact Registry:

   ### PKIX Cloud KMS

   Sign the image with a key hosted in Cloud KMS and push the
   signature to Artifact Registry:

       cosign sign \
           --key gcpkms://projects/${KMS_KEY_PROJECT_ID}/locations/${KMS_KEY_LOCATION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME} \
           ${IMAGE_TO_SIGN}

   ### Local key

   Sign the image with a local private key and push the signature to Artifact Registry.

       cosign sign --key ${PRIVATE_KEY_FILE} ${IMAGE_TO_SIGN}

3. Respond to Cosign prompt:

   After running the `cosign sign` command, Cosign asks if you want to
   upload the signature to the transparency log Rekor. Respond `y` or `n` to the prompts. To learn more about Rekor, see the [Rekor documentation](https://docs.sigstore.dev/logging/overview/).

### Manually verify the signature

To manually verify the signature, do the following:

1. Ensure the signature exists in Artifact Registry:

   ### Google Cloud console

   1. Go to the Artifact Registry page in the Google Cloud console.

      [Go to Artifact Registry](https://console.cloud.google.com/artifacts/)
   2. In the repositories list, click the name of the repository that contains your image.

   3. Click the name of the image that you signed.

   4. Locate the item containing the signature. This item has the tag:
      `sha256-[image digest].sig`. There should be only one item with the tag.

   5. Click **Manifest**.

   6. You should see a JSON-formatted file with various fields. Each signature resides
      in one element of the `layers` list, in the `annotations` map. The
      signatures are located at the key `dev.cosignproject.cosign/signature`.

      The following is an example manifest:

   ```json
     {
           "schemaVersion": 2,
           "mediaType": "application/vnd.oci.image.manifest.v1+json",
           "config": {
               "mediaType": "application/vnd.oci.image.config.v1+json",
               "size": SIZE_OF_LAYERS,
               "digest": "DIGEST_OF_LAYERS"
           },
           "layers": [
               {
                   "mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
                   "size": SIZE_OF_ANNOTATIONS,
                   "digest": "DIGEST_OF_ANNOTATIONS",
                   "annotations": {
                       "dev.cosignproject.cosign/signature": "BASE64_SIGNATURE",
                       "dev.sigstore.cosign/bundle": "BUNDLE"
                   }
               }
           ]
     }
   ```

   The example manifest includes the following:
   - `SIZE_OF_LAYERS`: size of the `layers` array in bytes
   - `DIGEST_OF_LAYERS`: the digest of the `layers` array
   - `SIZE_OF_ANNOTATIONS`: size of the `annotations` dictionary in bytes
   - `DIGEST_OF_ANNOTATIONS`: digest of the `annotations` dictionary
   - `BASE64_SIGNATURE`: The raw signature of encoded in base64 format. This is the signature that will be used for verification
   - `BUNDLE`: Sigstore specific metadata

   More details on the manifest format can be found in Sigstore's [cosign signature specification](https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md).

   ### Command line

   1. Find the correct artifact:

      List the items stored with the image:

          gcloud artifacts docker tags list ${IMAGE_PATH}

      An example output looks like the following:

      ```
      Listing items under project PROJECT_ID, location REPOSITORY_LOCATION, repository REPOSITORY_NAME.
      TAG                         IMAGE                                                         DIGEST
      latest                      us-east1-docker.pkg.dev/my-project/my-repo/my-image           sha256:abc123
      sha256-abc123.sig           us-east1-docker.pkg.dev/my-project/my-repo/my-image           sha256:def456
      ```

      In the output, the artifact with the tag `sha256-abc123.sig` contains
      the signature in its manifest.
   2. Get the manifest

      To obtain the manifest of the artifact with tag `sha256-IMAGE_DIGEST_SHA.sig`, run the following command:

          curl -X GET -H "Content-Type: application/json" \
                      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
                      -H "X-Goog-User-Project: REPOSITORY_PROJECT_ID" \
                      "https://REPOSITORY_LOCATION-docker.pkg.dev/v2/REPOSITORY_PROJECT_ID/REPOSITORY_NAME/IMAGE_NAME/manifests/sha256-IMAGE_DIGEST_SHA.sig"

      Replace the following:
      - `REPOSITORY_PROJECT_ID`: the ID of the project that contains the repository
      - `REPOSITORY_LOCATION`: the location of the repository
      - `REPOSITORY_NAME`: the name of the repository
      - `IMAGE_NAME`: the name of the image

      You should see a JSON-formatted file with various fields. Each signature resides
      in one element of the `layers` list, in the `annotations` map. The
      signatures are located at the key `dev.cosignproject.cosign/signature`.

      An example manifest is shown here:

      ```json
      {
          "schemaVersion": 2,
          "mediaType": "application/vnd.oci.image.manifest.v1+json",
          "config": {
              "mediaType": "application/vnd.oci.image.config.v1+json",
              "size": SIZE_OF_LAYERS,
              "digest": "DIGEST_OF_LAYERS"
          },
          "layers": [
              {
                  "mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
                  "size": SIZE_OF_ANNOTATIONS,
                  "digest": "DIGEST_OF_ANNOTATIONS",
                  "annotations": {
                      "dev.cosignproject.cosign/signature": "BASE64_SIGNATURE",
                      "dev.sigstore.cosign/bundle": "BUNDLE"
                  }
              }
          ]
      }
      ```

   The example manifest includes the following:
   - `SIZE_OF_LAYERS`: size of the `layers` array in bytes
   - `DIGEST_OF_LAYERS`: the digest of the `layers` array
   - `SIZE_OF_ANNOTATIONS`: size of the `annotations` dictionary in bytes
   - `DIGEST_OF_ANNOTATIONS`: digest of the `annotations` dictionary
   - `BASE64_SIGNATURE`: The raw signature of encoded in base64 format. This is the signature that will be used for verification
   - `BUNDLE`: Sigstore specific metadata

   More details on the manifest format can be found in Sigstore's [cosign signature specification](https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md).
2. Manually verify the signature:

   Use `cosign verify` to verify the uploaded signature:

   ### PKIX Cloud KMS

       cosign verify --key gcpkms://projects/${KMS_KEY_PROJECT_ID}/locations/${KMS_KEY_LOCATION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME} \
             ${IMAGE_PATH}@${IMAGE_DIGEST}

   ### Local key

       cosign verify --key {PUBLIC_KEY_FILE} ${IMAGE_PATH}@${IMAGE_DIGEST}

   > [!NOTE]
   > **Note:** Depending on whether you uploaded the signature to the public transparency log Rekor, you might need to add the `--insecure-ignore-tlog` command line flag in order to verify the signature.

   The command output states that `The signatures were verified against the
   specified public key` if the verification was successful.

### Deploy the signed image

To deploy a signed image, do the following:

1. Configure `kubectl`:

       gcloud container clusters get-credentials CLUSTER_NAME \
           --location=LOCATION \
           --project=CLUSTER_PROJECT_ID

   Replace the following:
   - `CLUSTER_NAME`: the name of your cluster
   - `LOCATION`: the cluster location
   - `CLUSTER_PROJECT_ID`: the cluster project ID
2. Deploy an image and check the deployment against the Binary Authorization
   policy:

       kubectl run hello-app-signed --image=${IMAGE_PATH}@${IMAGE_DIGEST}

   The Pod was deployed. Because the image is signed, CV doesn't
   produce log entries related to this Pod.

   > [!NOTE]
   > **Note:** If running into errors when deploying, you might have to grant the Compute Engine service agent permission to access the repository. Read the [Google Cloud SDK documentation](https://cloud.google.com/sdk/gcloud/reference/artifacts/repositories/add-iam-policy-binding).

### Deploy an unsigned image

In this section, you deploy an unsigned image.

Because the policy requires signatures and this image doesn't have one,
CV regularly logs the violation while the container is running.

To deploy the image, run the following command:

      kubectl run hello-app-unsigned \
          --image=UNSIGNED_IMAGE_PATH@UNSIGNED_IMAGE_DIGEST

The Pod was deployed. Because the image doesn't have an attestation,
CV produces [log entries](https://docs.cloud.google.com/binary-authorization/docs/cv-sigstore-check#view-logs) while the
Pod is running.

## View logs for CV entries

You can search Cloud Logging entries to find [CV configuration errors](https://docs.cloud.google.com/binary-authorization/docs/cv-sigstore-check#view-config-errors)
and [CV platform policy validation violations](https://docs.cloud.google.com/binary-authorization/docs/cv-sigstore-check#view-validation-violations).

CV logs errors and violations to Cloud Logging
within 24 hours. You can usually see entries within a few hours.

### View CV configuration error logs

To view CV configuration error logs, run the following command:

    gcloud logging read \
         --order="desc" \
         --freshness=7d \
         --project=CLUSTER_PROJECT_ID \
        'logName:"binaryauthorization.googleapis.com%2Fcontinuous_validation" "configErrorEvent"'

The following output shows a configuration error in which a CV
platform policy isn't found:

    {
      "insertId": "141d4f10-72ea-4a43-b3ec-a03da623de42",
      "jsonPayload": {
        "@type": "type.googleapis.com/google.cloud.binaryauthorization.v1beta1.ContinuousValidationEvent",
        "configErrorEvent": {
          "description": "Cannot monitor cluster 'us-central1-c.my-cluster': Resource projects/123456789/platforms/gke/policies/my-policy does not exist."
        }
      },
      "resource": {
        "type": "k8s_cluster",
        "labels": {
          "cluster_name": "my-cluster",
          "location": "us-central1-c",
          "project_id": "my-project"
        }
      },
      "timestamp": "2024-05-28T15:31:03.999566Z",
      "severity": "WARNING",
      "logName": "projects/my-project/logs/binaryauthorization.googleapis.com%2Fcontinuous_validation",
      "receiveTimestamp": "2024-05-28T16:30:56.304108670Z"
    }

### View CV platform policy validation violations

If no images violate the platform policies that you have enabled, no entries
appear in the logs.

To view CV log entries for the last seven days, run the following
command:

    gcloud logging read \
         --order="desc" \
         --freshness=7d \
         --project=CLUSTER_PROJECT_ID \
        'logName:"binaryauthorization.googleapis.com%2Fcontinuous_validation" "policyName"'

Replace `CLUSTER_PROJECT_ID` with the cluster project ID.

#### Check types

CV logs check violation information to `checkResults`. In the
entry, the value `checkType` indicates the check. The values for each check are
as follows:

- `ImageFreshnessCheck`
- `SigstoreSignatureCheck`
- `SimpleSigningAttestationCheck`
- `SlsaCheck`
- `TrustedDirectoryCheck`
- `VulnerabilityCheck`

#### Example log

The following example CV Logging entry describes
a non-conformant image that violates a [trusted directory check](https://docs.cloud.google.com/binary-authorization/docs/overview-cv#trusted-directory-check):

    {
      "insertId": "637c2de7-0000-2b64-b671-24058876bb74",
      "jsonPayload": {
        "podEvent": {
          "endTime": "2022-11-22T01:14:30.430151Z",
          "policyName": "projects/123456789/platforms/gke/policies/my-policy",
          "images": [
            {
              "result": "DENY",
              "checkResults": [
                {
                  "explanation": "TrustedDirectoryCheck at index 0 with display name \"My trusted directory check\" has verdict NOT_CONFORMANT. Image is not in a trusted directory",
                  "checkSetName": "My check set",
                  "checkSetIndex": "0",
                  "checkName": "My trusted directory check",
                  "verdict": "NON_CONFORMANT",
                  "checkType": "TrustedDirectoryCheck",
                  "checkIndex": "0"
                }
              ],
              "image": "gcr.io/my-project/hello-app:latest"
            }
          ],
          "verdict": "VIOLATES_POLICY",
          "podNamespace": "default",
          "deployTime": "2022-11-22T01:06:53Z",
          "pod": "hello-app"
        },
        "@type": "type.googleapis.com/google.cloud.binaryauthorization.v1beta1.ContinuousValidationEvent"
      },
      "resource": {
        "type": "k8s_cluster",
        "labels": {
          "project_id": "my-project",
          "location": "us-central1-a",
          "cluster_name": "my-test-cluster"
        }
      },
      "timestamp": "2022-11-22T01:44:28.729881832Z",
      "severity": "WARNING",
      "logName": "projects/my-project/logs/binaryauthorization.googleapis.com%2Fcontinuous_validation",
      "receiveTimestamp": "2022-11-22T03:35:47.171905337Z"
    }

## Clean up

This section describes how to clean up the CV monitoring you
configured earlier in this guide.

You can disable CV monitoring or both Binary Authorization
and CV in your cluster.

### Disable Binary Authorization in a cluster

To disable both CV and Binary Authorization enforcement in your
cluster, run the following command:

    gcloud beta container clusters update CLUSTER_NAME \
        --binauthz-evaluation-mode=DISABLED \
        --location=LOCATION \
        --project=CLUSTER_PROJECT_ID

Replace the following:

- `CLUSTER_NAME`: the name of the cluster
- `LOCATION`: the cluster location
- `CLUSTER_PROJECT_ID`: the cluster project ID

### Disable check-based policy monitoring in a cluster

To disable CV with check-based policies in the cluster, and
re-enable enforcement using the Binary Authorization enforcement policy, run
the following command:

    gcloud beta container clusters update CLUSTER_NAME  \
        --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
        --location=LOCATION \
        --project="CLUSTER_PROJECT_ID"

Replace the following:

- `CLUSTER_NAME`: the name of the cluster
- `LOCATION`: the cluster location
- `CLUSTER_PROJECT_ID`: the cluster project ID

Note that `--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE` is
equivalent to the older flag `--enable-binauthz`.

### Delete the policy

To delete the policy, run the following command. It is not necessary to delete
the check-based platform policy to disable check-based policy auditing.

    gcloud beta container binauthz policy delete POLICY_ID \
        --platform=gke \
        --project="POLICY_PROJECT_ID"

Replace the following:

- `POLICY_ID`: the ID of the policy
- `POLICY_PROJECT_ID`: the policy project ID

## What's next

- [Use the image freshness check](https://docs.cloud.google.com/binary-authorization/docs/cv-freshness-check)
- [Use the simple signing attestation check](https://docs.cloud.google.com/binary-authorization/docs/cv-attestation-check)
- [Use the Sigstore signature check](https://docs.cloud.google.com/binary-authorization/docs/cv-sigstore-check)
- [Use the SLSA check](https://docs.cloud.google.com/binary-authorization/docs/cv-slsa-check)
- [Use the trusted directory check](https://docs.cloud.google.com/binary-authorization/docs/cv-trusted-directory-check)
- [Use the vulnerability check](https://docs.cloud.google.com/binary-authorization/docs/cv-vulnerability-check)
- [View CV logs](https://docs.cloud.google.com/binary-authorization/docs/cv-view-logs)