Enforce policies in CI/CD
Fail a CI/CD build when an SBOM breaks a policy, with a fail-build action and observer analyze --fail.
A policy violation fails a CI/CD build only when all three of these are true:
- The violation has the action
fail-build. Only Rego and JavaScript policies can set it, on each violation they return; Visual Builder policies report violations without an action. - The pipeline runs
observer analyze --fail. - The CLI can sign in to your namespace, so
analyzeevaluates your namespace's policies. Without that,analyzeuses a temporary namespace that doesn't have your policies. The next section shows how to set it up.
If any is missing, violations are printed and the build continues. That is also the way to try out a new policy: run without --fail first and read the output.
Before starting, install Observer CLI in the pipeline.
Give the CLI access to your namespace
Observer CLI has no login command. It reads an access token from the environment variable OBSERVER_TOKEN, and the namespace from OBSERVER_NAMESPACE.
Create an access token
Sign in to SBOM Observer, open the user menu in the lower-left corner, select Access Tokens, and create a token in the namespace whose policies the pipeline should use. Copy it; it is shown only once.
Store it as a pipeline secret
Add the token to your CI/CD system as a secret, for example a repository secret named OBSERVER_TOKEN in GitHub Actions. Never commit it to the repository.
Pass it to the steps that run the CLI
Map the secret to the environment variable OBSERVER_TOKEN in every step that runs observer analyze or observer upload. If the namespace isn't called default, also set OBSERVER_NAMESPACE to its name, the part of the app URL after /workspace/. In GitHub Actions:
env:
OBSERVER_TOKEN: ${{ secrets.OBSERVER_TOKEN }}
OBSERVER_NAMESPACE: ${{ vars.OBSERVER_NAMESPACE }}Other CI systems have the same mechanism under another name, such as masked variables or credentials. To try it in a terminal, run export OBSERVER_TOKEN=<token> first.
Write a policy that fails builds
This JavaScript policy returns a fail-build violation for each vulnerability with severity above 5 and EPSS above 0.5, unless a VEX analysis says it isn't exploitable:
// consider these VEX states as not "exploitable" and therefore not a violation
const nonExploitableVexStates = new Set([
"not_affected",
"false_positive",
"resolved",
"resolved_with_pedigree",
]);
function Policy({ component, vulnerabilities }) {
if (vulnerabilities && vulnerabilities.length > 0) {
return vulnerabilities
.filter((vulnerability) => vulnerability.severity > 5)
.filter((vulnerability) => vulnerability.epss > 0.5)
.filter(
(vulnerability) =>
!vulnerability.vex ||
!nonExploitableVexStates.has(vulnerability.vex.state),
)
.map((vulnerability) => ({
severity: vulnerability.severity,
message: `${vulnerability.vendorId} with severity > 5 (${vulnerability.severity}) and EPSS > 0.5 (${vulnerability.epss}) is not tolerated for a library`,
action: "fail-build",
}));
}
return null;
}Create it under Policies with scope Components. See Write and test policies for the Rego form and testing.
Run it in the pipeline
Generate the SBOM
observer fs -o sbom.cdx.json .Verify it (optional)
observer verify sbom.cdx.json --artifacts ./distChecks the SBOM is well-formed; --artifacts also checks it against the built files.
Analyze with --fail
observer analyze --fail sbom.cdx.jsonExits with code 1 when a fail-build violation is returned, which fails the pipeline step.
Upload
observer upload sbom.cdx.jsonRun this only when the previous step passed, so the namespace holds SBOMs of builds that passed. Add retention flags to archive older versions.
For a complete GitHub Actions workflow with these steps, see CI/CD integration.
Next steps
- Write and test policies
- CLI reference
- Concept: Policies
Compare two SBOMs
See which components, vulnerabilities, and policy violations changed between two SBOMs, for example two releases of one application.
Evaluate open source components
Check the open source project behind a component on the OSS Insights tab, with repository activity, the OpenSSF Scorecard, and SLSA provenance.