Generate complete Conforma validation setup for container images. Creates policy rules, tests, configuration, and ready-to-run commands. Users don't need to know Rego, Conforma, or SBOM formats.
Help users validate container images with Conforma policies. The user doesn't need to know anything about Rego, Conforma, SBOMs, or policy configuration - this skill handles everything.
| Input | Description | Example |
|---|---|---|
| Policy set name | Descriptive name for the policy set | release_policies |
| Image reference | Container image to validate (optional) | quay.io/org/app@sha256:abc123... |
| Public key | Cosign public key file (optional) | cosign.pub |
| Validation requirements | What they want to check | "Ensure npm packages come from registry.npmjs.org" |
See Policy Requirements Template for a complete requirements checklist.
When a user requests policy validation, generate these artifacts:
| Artifact | Description |
|---|---|
Policy rule (.rego) | Standalone Rego v1 rule |
Test file (_test.rego) | Comprehensive tests for the rule |
Policy config (policy.yaml) | Conforma configuration referencing data files |
Data file (data/*.yaml) | Rule data configuration (e.g., allowed registries) |
| Conforma command | Ready-to-run ec validate image command |
| Instructions | Clear next steps for the user |
allowed_package_sources for SBOM rules)ec opa test ./policy -v and ensure ALL tests passec validate image and verify expected resultsYOU ARE NOT DONE UNTIL THESE STEPS PASS. DO NOT REPORT SUCCESS TO THE USER UNTIL VERIFICATION IS COMPLETE.
After creating all Rego files, you MUST run the tests:
cd <policy_set_directory>
ec opa test ./policy -v --ignore '*.rego' --ignore 'lib/*'
Note: We exclude lib/* because sbom.rego uses ec.oci.blob() which OPA can't parse.
Tests must mock data.lib.sbom.spdx_sboms directly.
Requirements:
If the user provided an image reference, you MUST validate the policy against it:
cd <policy_set_directory>
ec validate image \
--image <IMAGE_REFERENCE> \
--policy policy.yaml \
--public-key cosign.pub \
--ignore-rekor \
--output text \
--info
Requirements:
If validation doesn't produce expected results:
For Rego lint compliance, directory path must match package name. Use a descriptive top-level directory name, with rules organized under a policy/ subdirectory:
<descriptive_name>/ # e.g., release_policies, sbom_validation
├── policy.yaml # Conforma configuration
├── cosign.pub # Public key (if provided)
├── data/ # Rule data files (referenced from policy.yaml)
│ └── <rule_data>.yaml # YAML file with rule_data configuration
└── policy/ # Contains all rule directories
├── lib/ # Shared library (required for SBOM rules)
│ └── sbom.rego # SBOM access library
└── <rule_name>/ # Directory matches package name
├── <rule_name>.rego # package <rule_name>
└── <rule_name>_test.rego # package <rule_name>_test
Example - For release policies with a package_sources rule:
release_policies/
├── policy.yaml
├── cosign.pub
├── data/
│ └── allowed_sources.yaml # rule_data for allowed package sources
└── policy/
├── lib/
│ └── sbom.rego # package lib.sbom
└── package_sources/
├── package_sources.rego # package package_sources
└── package_sources_test.rego # package package_sources_test
IMPORTANT: SBOMs are NOT directly embedded in attestations. In Konflux/RHTAP builds, the SBOM is stored as an OCI blob and referenced from the SLSA provenance attestation. The library fetches these using ec.oci.blob().
For any rule that validates SBOM data, you MUST:
Create the SBOM library at policy/lib/sbom.rego using the SBOM Library Template
Include the lib and data in policy.yaml:
sources:
- name: my-rules
data:
- ./data # Rule data files
policy:
- ./policy/lib # SBOM access library
- ./policy/my_rule
Import and use in your rules:
import data.lib.sbom
deny contains result if {
some s in sbom.spdx_sboms # Fetches from OCI blobs via ec.oci.blob()
some pkg in s.packages
# validation logic
}
Mock the SBOM data in tests (CRITICAL):
test_my_rule if {
sboms := [_mock_spdx_sbom(packages)]
count(my_rule.deny) == 1
with data.lib.sbom.spdx_sboms as sboms # MUST mock - bypasses ec.oci.blob()
}
How it works:
ec.oci.blob() to fetch SBOMs from OCI blobs referenced in SLSA provenanceec.oci.blob() is an EC built-in function that OPA doesn't understanddata.lib.sbom.spdx_sboms directly to bypass the library implementationTesting Note: OPA tests will fail if they try to evaluate sbom.rego directly because OPA can't parse ec.oci.blob(). Always mock data.lib.sbom.spdx_sboms in tests.
DO NOT iterate directly over input.attestations for SBOM data - always use the library.
Run from within the policy set directory (e.g., cd release_policies):
ec validate image \
--image <IMAGE_REFERENCE> \
--policy policy.yaml \
--public-key cosign.pub \
--ignore-rekor \
--output text \
--info
Important: The policy.yaml references rules with relative paths (./policy/<rule_name>), so the command must be run from the policy set directory where policy.yaml is located.
package <rule_name>
import rego.v1
import data.lib.sbom # Use the SBOM library
# METADATA
# title: Rule Title
# description: >-
# What the rule checks.
# custom:
# short_name: rule_name
# failure_msg: "Error: %s"
# solution: How to fix.
deny contains result if {
# Use sbom.spdx_sboms or sbom.cyclonedx_sboms (NOT input.attestations)
some s in sbom.spdx_sboms
some pkg in s.packages
# validation logic
result := {
"code": "<rule_name>.rule_name",
"msg": sprintf("Error: %s", [value]),
"severity": "failure",
}
}