This feature is only available on Chainloop’s platform paid plans.
Overview
Chainloop lets you manage compliance resources declaratively by defining them as YAML files and applying them via the CLI. This GitOps-friendly approach means you can:
- Version-control resource definitions alongside your code
- Review changes through pull requests before they take effect
- Automate resource management in CI/CD pipelines
- Reproduce configurations across environments
All resources follow a Kubernetes-style schema with apiVersion, kind, metadata, and spec fields. Apply operations are idempotent—if a resource with the same name already exists, it is updated; otherwise, a new one is created.
Supported Resources
| Kind | Description |
|---|
Framework | Groups requirements into compliance frameworks |
Requirement | Defines policies and manual proofs for compliance |
Policy | Custom policy with Rego rules |
PolicyGroup | Reusable group of related policies |
Contract | Workflow contract defining attestation expectations |
For full details on each resource type, see Compliance Frameworks, Policies, Policy Groups, and Contracts.
Getting Started
Before you begin, make sure you have:
- Chainloop CLI Enterprise Edition installed - see the CLI installation guide
- Authenticated to your organization - run
chainloop auth login
This walkthrough builds a complete compliance-as-code setup from scratch around an SBOM license-compliance use case. Each step builds on the previous one - by the end you’ll have a policy, a policy group, a requirement, a framework, and a contract that all work together.
The steps below apply each resource individually so you can verify as you go. In practice, you can place all your YAML files in a single directory and apply them at once with chainloop apply -f ./compliance/ - Chainloop resolves dependencies automatically. See Applying Resources at Scale.
Step 1 - Write a Policy
A policy contains the Rego rules that Chainloop evaluates against your attestation materials. Start by defining one that checks CycloneDX SBOMs for components missing license information.
Create cyclonedx-licenses.yaml:
apiVersion: workflowcontract.chainloop.dev/v1
kind: Policy
metadata:
name: cyclonedx-licenses
description: Checks for components without licenses
annotations:
category: sbom
spec:
policies:
# kind determines which material type this policy evaluates
- kind: SBOM_CYCLONEDX_JSON
# Rego code inline - you can also use `ref` to point to an external .rego file
embedded: |
package main
import rego.v1
valid_input if {
count(input.components) > 0
}
violations contains msg if {
some comp in input.components
not comp.licenses
msg := sprintf("Missing license for %s", [comp.purl])
}
Apply and verify:
chainloop policy apply --file cyclonedx-licenses.yaml
chainloop policy describe --name cyclonedx-licenses
Step 2 - Group Policies Together
A policy group bundles related policies into a reusable unit. Let’s create one that groups the cyclonedx-licenses policy from Step 1 with another SBOM policy to form a complete SBOM quality check.
Create sbom-quality-group.yaml:
apiVersion: workflowcontract.chainloop.dev/v1
kind: PolicyGroup
metadata:
name: sbom-quality
description: >-
SBOM quality policies - checks that SBOMs contain
license and dependency information.
annotations:
category: sbom
spec:
inputs:
- name: bannedLicenses
description: Comma-separated list of licenses to ban (e.g., AGPL-1.0-only)
# default provides a fallback when the caller doesn't supply a value
default: ""
policies:
# attestation policies run against the envelope itself
attestation:
- ref: sbom-present
# materials policies run against individual attached artifacts
materials:
- policies:
# The custom policy from Step 1
- ref: cyclonedx-licenses
# A built-in policy that ships with Chainloop
- ref: sbom-banned-licenses
with:
licenses: "{{ inputs.bannedLicenses }}"
The group includes the cyclonedx-licenses policy you just created alongside sbom-banned-licenses, a built-in policy that ships with Chainloop. The attestation section checks that an SBOM was included in the attestation; the materials section runs quality checks against the SBOM itself.
Apply and verify:
chainloop policy-group apply --file sbom-quality-group.yaml
chainloop policy-group describe --name sbom-quality
For full details on policy group structure and capabilities, see Policy Groups.
Step 3 - Define a Requirement
A requirement specifies what must be satisfied for compliance - which policies to evaluate, how often, and what manual evidence is needed. Let’s create one that enforces license compliance by referencing the policy from Step 1.
Create license-compliance.yaml:
apiVersion: chainloop.dev/v1
kind: Requirement
metadata:
name: license-compliance
displayName: License Compliance
description: |
All software artifacts must include license information
and must not use banned licenses.
annotations:
categories: security, licensing
spec:
policies:
# The custom policy from Step 1
- ref: cyclonedx-licenses
# A built-in policy that ships with Chainloop
- ref: sbom-banned-licenses
# with passes parameters to the policy
with:
licenses: "AGPL-1.0-only,AGPL-3.0-only"
Requirements can also include periodicity (how often a policy is re-evaluated, e.g. daily, weekly), sla (grace period in hours before failures affect the compliance score), and manual_proofs for evidence that can’t be automated (e.g., license review sign-offs). For the full schema, see Compliance Frameworks.
Apply and verify:
chainloop requirement apply --file license-compliance.yaml
chainloop requirement describe --name license-compliance
Step 4 - Build a Framework
A framework organizes requirements into a structured compliance program. You can group requirements into sections (and nested sub-sections) to model standards like CRA, SLSA, or your own internal policies. Let’s build one that includes the requirement from Step 3.
Create best-practices.yaml:
apiVersion: chainloop.dev/v1
kind: Framework
metadata:
name: my-best-practices
displayName: Best Practices
description: Internal security and compliance best practices
spec:
sections:
- name: Source Code
description: Source code integrity and secure development practices.
requirements:
# Built-in requirements that ship with Chainloop
- ref: branch-protection
- ref: code-review
- name: Supply Chain
description: Ensure software dependencies are properly licensed.
requirements:
# The custom requirement from Step 3
- ref: license-compliance
This framework mixes built-in requirements (branch-protection, code-review) with the custom license-compliance requirement you created in Step 3. Chainloop ships with a library of built-in requirements and policies - your custom resources extend them.
Apply and verify:
chainloop framework apply --file best-practices.yaml
chainloop framework describe --name my-best-practices
Each requirement can only appear once in a framework - either at the root level or within a section, not both.
Step 5 - Tie It Together in a Contract
A contract defines the attestation expectations for a workflow - what materials to collect and which policies and policy groups to evaluate. This is where everything comes together: the contract references the policy group from Step 2, which in turn includes the policy from Step 1.
Create example-contract.yaml:
apiVersion: chainloop.dev/v1
kind: Contract
metadata:
name: example-contract
spec:
policyGroups:
# The policy group from Step 2 (which includes the policy from Step 1)
- ref: sbom-quality
with:
bannedLicenses: AGPL-1.0-only,AGPL-3.0-only
When a workflow attests against this contract, Chainloop will check that an SBOM is present, verify every component has a license, and flag any banned licenses - all driven by the resources you built in the previous steps.
Apply and verify:
chainloop apply -f example-contract.yaml
chainloop contract describe --name example-contract
For the full contract schema including material types and runner context, see Contracts.
Applying Resources at Scale
The steps above apply resources one at a time. The chainloop apply command can handle any resource type, including multi-document YAML files and entire directories:
# Apply a single file (can contain multiple resources separated by ---)
chainloop apply -f compliance-resources.yaml
# Apply all YAML files in a directory
chainloop apply -f ./compliance/
When applying multiple resources, Chainloop processes them in dependency order: Policies, then Policy Groups, then Requirements, then Frameworks, then Contracts. Multi-document YAML files use --- as the separator between resources.
Inspecting and Exporting Resources
After applying resources, you can verify them, explore what’s deployed, and export definitions for backup or migration.
Export a resource as reusable YAML with the --output schema flag - useful for bootstrapping new configurations, backing up resources, or migrating between organizations:
chainloop policy describe --name cyclonedx-licenses --output schema
chainloop requirement describe --name license-compliance --output schema
chainloop framework describe --name my-best-practices --output schema
Add --output json to any describe or list command for JSON output.
Automating with CI/CD
Store your YAML resource definitions in a git repository and apply them automatically whenever changes are merged. This ensures compliance configurations are always up to date and auditable. You’ll need an API token stored as a CI secret.
name: Apply Compliance Resources
on:
push:
branches: [main]
paths: ['compliance/**']
jobs:
apply:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Chainloop CLI
run: curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s -- --ee
- name: Apply resources
run: chainloop apply -f ./compliance/
env:
CHAINLOOP_TOKEN: ${{ secrets.CHAINLOOP_TOKEN }}
apply-compliance:
stage: deploy
script:
- curl -sfL https://dl.chainloop.dev/cli/install.sh | bash -s -- --ee
- chainloop apply -f ./compliance/
rules:
- changes: [compliance/**]
variables:
CHAINLOOP_TOKEN: $CHAINLOOP_TOKEN