In the previous step, we created a contract that set the expectation of a container image and an optional SBOM. Our Compliance team now wants to verify that those comply with the company’s security and compliance criteria.

We introduce Policies, which are rules evaluated against materials and/or the whole attestation document.

See our Policies reference for more information.

Adding policies to the contract

Click on “Create contract”, and create a new contract with the name “qs-policies”, and with the following schema:

schemaVersion: v1
materials:
  - name: container
    type: CONTAINER_IMAGE
  - name: sbom
    type: SBOM_CYCLONEDX_JSON
    optional: true
policies:
  materials:
    # artifact-signed checks that all OCI artifacts such as Container Images and Charts are signed
    - ref: artifact-signed
    # sbom-version checks the expected version for a CycloneDX report.
    - ref: sbom-version
      with:
        min_version: "1.6"

In this contract, we added two policies.

  • artifact-signed policy checks that all OCI artifacts (container images and Helm Charts) are properly signed with Cosign or Notary
  • sbom-version checks that the provided SBOMs have a minimum version (CycloneDX 1.6 in this case)

Chainloop comes with a set of built-in policies, you can see them all in the “Policies” section:

You can also create custom policies tailored to your needs. For more information about authoring policies, see the TODO

Evaluating policies

Let’s create an attestation and add our materials to see how policies are evaluated:

1

Initialize an attestation

chainloop att init --workflow qs-policies --project myproject --contract qs-policies --replace
2

Add the container image

chainloop att add --name container --value ghcr.io/chainloop-dev/chainloop/control-plane

You’ll notice how Chainloop will evaluate automatically as part of providing the container image.

3

Add the SBOM

chainloop att add --name sbom --value https://raw.githubusercontent.com/chainloop-dev/chainloop/refs/heads/main/docs/examples/quickstart/sbom.json
4

Push the attestation

chainloop att push
INF push completed
┌───────────────────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Initialized At            │ 14 Mar 25 12:59 UTC                                                     │
├───────────────────────────┼─────────────────────────────────────────────────────────────────────────┤
│ Attestation ID            │ cd1a6c19-3de0-4d33-b810-a6cbcf489a73                                    │
│ Digest                    │ sha256:3f331287f32b685abece1603c0a5a777fe17c6484291bd8fbb8939b20b190754 │
│ Organization              │ silly-greider-943                                                       │
│ Name                      │ qs-policies                                                             │
│ Project                   │ myproject                                                               │
│ Version                   │ none                                                   │
│ Contract                  │ qs-policies (revision 2)
│ Timestamp Authority       │ http://timestamp.digicert.com                                           │
│ Policy violation strategy │ ADVISORY                                                                │
└───────────────────────────┴─────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│ Materials                                                                          │
├──────────┬─────────────────────────────────────────────────────────────────────────┤
│ Name     │ container                                                               │
│ Type     │ CONTAINER_IMAGE                                                         │
│ Set      │ Yes                                                                     │
│ Required │ Yes                                                                     │
│ Value    │ ghcr.io/chainloop-dev/chainloop/control-plane:latest                    │
│ Digest   │ sha256:1872ea6f4758de022e127de8b8062db2937195e2ebb30fef6af2271b156f5cd7 │
│ Policies │ ------                                                                  │
│          │ artifact-signed: Ok                                                     │
├──────────┼─────────────────────────────────────────────────────────────────────────┤
│ Name     │ sbom                                                                    │
│ Type     │ SBOM_CYCLONEDX_JSON                                                     │
│ Set      │ Yes                                                                     │
│ Required │ No                                                                      │
│ Value    │ sbom.json                                                               │
│ Digest   │ sha256:f2888d10bcd93dc58431049a13acac1bc402231fb066e9e58fd986d91dec05f1 │
│ Policies │ ------                                                                  │
│          │ sbom-version: Ok                                                        │
└──────────┴─────────────────────────────────────────────────────────────────────────┘

We can confirm that the sbom-version policy was evaluated successfully. Policy evaluations are part of the attestation, and thus they are immutable and stored in Chainloop’s evidence store for the long term.

Inspecting policy evaluations

Now, the Chainloop platform gives us more insights into the status of the attestation. If we go to the workflow run view, besides the usual attestation and material information, we can now see the result of those policy evaluations.