-
Notifications
You must be signed in to change notification settings - Fork 53
chore(docs): Create quickstart and examples for policy devel CLI tools #2298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| # Policy Development Quickstart | ||
|
|
||
| This quickstart guide walks you through creating and validating a basic Chainloop policy that checks SBOM freshness (ensuring SBOMs are not older than 30 days). All steps are CLI-driven and can be run locally. | ||
|
|
||
| ## Documentation References | ||
|
|
||
| - **CLI Reference**: [chainloop policy develop commands](https://docs.chainloop.dev/command-line-reference/cli-reference#chainloop-policy) | ||
| - **Policy Concepts**: [Understanding Chainloop Policies](https://docs.chainloop.dev/concepts/policies) | ||
| - **Custom Policy Guide**: [Writing Custom Policies](https://docs.chainloop.dev/guides/custom-policies) | ||
| - **Material Types**: [Available Material Types](https://docs.chainloop.dev/concepts/material-types#material-types) | ||
|
|
||
| ## Quick Test | ||
|
|
||
| ### Step 1: Download the Example Files | ||
|
|
||
| ```bash | ||
| # Download the policy and sample materials | ||
| curl -O https://raw.githubusercontent.com/chainloop-dev/chainloop/refs/heads/main/docs/examples/policies/quickstart/cdx-fresh.yaml | ||
| curl -O https://raw.githubusercontent.com/chainloop-dev/chainloop/refs/heads/main/docs/examples/policies/quickstart/cdx-old.json | ||
| curl -O https://raw.githubusercontent.com/chainloop-dev/chainloop/refs/heads/main/docs/examples/policies/quickstart/cdx-fresh.json | ||
| ``` | ||
|
|
||
| ### Step 2: Lint the Policy | ||
|
|
||
| Check your policy's structure and Rego syntax. Run it with `--format` flag to fix all formatting inconsistencies. | ||
|
|
||
| ```bash | ||
| chainloop policy develop lint --policy cdx-fresh.yaml --format | ||
| ``` | ||
|
|
||
| **Expected output:** | ||
| ``` | ||
| INF policy is valid! | ||
| ``` | ||
|
|
||
| ### Step 3: Evaluate the Policy | ||
|
|
||
| Use your SBOM CycloneDX material to test your policy logic. | ||
|
|
||
| ```bash | ||
| # Test with old SBOM (should fail) | ||
| chainloop policy develop eval --policy cdx-fresh.yaml --material cdx-old.json --kind SBOM_CYCLONEDX_JSON | ||
|
|
||
| # Test with fresh SBOM (should pass) | ||
| chainloop policy develop eval --policy cdx-fresh.yaml --material cdx-fresh.json --kind SBOM_CYCLONEDX_JSON | ||
| ``` | ||
|
|
||
| **Expected Results:** | ||
|
|
||
| **Old SBOM (should fail):** | ||
| ``` | ||
| INF - cdx-fresh: SBOM created at: 2024-06-15T10:30:00Z which is too old (freshness limit set to 30 days) | ||
| INF policy evaluation failed | ||
| ``` | ||
|
|
||
| **Fresh SBOM (should pass):** | ||
| ``` | ||
| INF policy evaluation passed | ||
| ``` | ||
|
|
||
| ## Create Your Own Policy | ||
|
|
||
| ### Step 1: Initialize a Policy Template | ||
|
|
||
| Create a new policy with the embedded format (single YAML file): | ||
|
|
||
| ```bash | ||
| chainloop policy develop init --embedded --name my-policy --description "My custom policy description" | ||
| ``` | ||
|
|
||
| **Note**: This creates a file named `my-policy.yaml` (based on the `--name` parameter). Without `--embedded`, it creates separate `chainloop-policy.yaml` and `chainloop-policy.rego` files. | ||
|
|
||
| ### Step 2: Write Your Policy Rules | ||
|
|
||
| Edit the generated YAML file and replace the placeholder code in the `embedded` section with your Rego logic. | ||
|
|
||
| **Important**: Remove the `default violations := []` line to avoid conflicts with your `violations contains msg if` rules. | ||
|
|
||
| ### Step 3: Test Your Policy | ||
|
|
||
| Follow steps 2-3 above with your own policy and materials. | ||
|
|
||
| ## Policy Logic Explained | ||
|
|
||
| The SBOM freshness policy calculates a 30-day threshold in nanoseconds and compares it against the SBOM's `metadata.timestamp` field: | ||
|
|
||
| 1. **Converts 30 days to nanoseconds**: `30 * 24 * 60 * 60 * 1000 * 1000 * 1000` | ||
| 2. **Parses the SBOM timestamp** using `time.parse_rfc3339_ns()` | ||
| 3. **Checks if current time minus (SBOM time + threshold) is positive** | ||
| 4. **If positive, the SBOM is too old** and a violation is raised | ||
|
|
||
| ## Available Material Types | ||
|
|
||
| For the complete list of supported material types, see the [Material Types documentation](https://docs.chainloop.dev/concepts/material-types#material-types). | ||
|
|
||
| Common material types for the `--kind` parameter: | ||
|
|
||
| - `SBOM_CYCLONEDX_JSON` - CycloneDX SBOM files | ||
| - `SBOM_SPDX_JSON` - SPDX SBOM files | ||
| - `CONTAINER_IMAGE` - Container images | ||
| - `ATTESTATION` - Generic attestations | ||
| - `SARIF` - SARIF security scan results | ||
| - `SLSA_PROVENANCE` - SLSA provenance attestations | ||
|
|
||
| Run `chainloop policy develop eval --help` for the complete list. | ||
|
|
||
| ## Common Issues | ||
|
|
||
| 1. **Rego type conflicts**: Remove `default violations := []` when using `violations contains msg if` rules | ||
| 2. **Missing material kind**: Always specify `--kind` parameter in eval command | ||
| 3. **File naming**: Policy files are named based on the `--name` parameter, not always `policy.yaml` | ||
| 4. **Time calculations**: Use nanoseconds for time comparisons in Rego policies | ||
|
|
||
| ## Next Steps | ||
|
|
||
| Once you've mastered the basics: | ||
|
|
||
| 1. Explore more complex examples in the [policy examples]](../) directory | ||
| 2. Learn about policy inputs and annotations | ||
| 3. Practice with different material types | ||
| 4. Deploy policies to your Chainloop workflows | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "bomFormat": "CycloneDX", | ||
| "specVersion": "1.5", | ||
| "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b80", | ||
| "version": 1, | ||
| "metadata": { | ||
| "timestamp": "2025-07-27T10:30:00Z", | ||
| "tools": [ | ||
| { | ||
| "vendor": "chainloop", | ||
| "name": "chainloop", | ||
| "version": "0.1.0" | ||
| } | ||
| ] | ||
| }, | ||
| "components": [ | ||
| { | ||
| "type": "library", | ||
| "bom-ref": "pkg:npm/express@4.18.0", | ||
| "name": "express", | ||
| "version": "4.18.0", | ||
| "purl": "pkg:npm/express@4.18.0" | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| apiVersion: workflowcontract.chainloop.dev/v1 | ||
| kind: Policy | ||
| metadata: | ||
| name: cdx-fresh | ||
| description: Checks that SBOM is maximum of 30 days old | ||
| annotations: | ||
| category: quickstart | ||
| spec: | ||
| policies: | ||
| - embedded: | | ||
| package main | ||
|
|
||
| import rego.v1 | ||
|
|
||
| ################################ | ||
| # Common section do NOT change # | ||
| ################################ | ||
|
|
||
| result := { | ||
| "skipped": skipped, | ||
| "violations": violations, | ||
| "skip_reason": skip_reason, | ||
| "ignore": ignore, | ||
| } | ||
|
|
||
| default skip_reason := "" | ||
|
|
||
| skip_reason := m if { | ||
| not valid_input | ||
| m := "invalid input" | ||
| } | ||
|
|
||
| default skipped := true | ||
|
|
||
| skipped := false if valid_input | ||
|
|
||
| default ignore := false | ||
|
|
||
| ######################################## | ||
| # EO Common section, custom code below # | ||
| ######################################## | ||
| # Validates if the input is valid and can be understood by this policy | ||
| valid_input := true | ||
|
|
||
| limit := 30 | ||
| nanosecs_per_second := (1000 * 1000) * 1000 | ||
| nanosecs_per_day := ((24 * 60) * 60) * nanosecs_per_second | ||
| maximum_age := limit * nanosecs_per_day | ||
|
|
||
| # If the input is valid, check for any policy violation here | ||
| violations contains msg if { | ||
| sbom_ns = time.parse_rfc3339_ns(input.metadata.timestamp) | ||
| exceeding = time.now_ns() - (sbom_ns + maximum_age) | ||
| exceeding > 0 | ||
| msg := sprintf("SBOM created at: %s which is too old (freshness limit set to %d days)", [input.metadata.timestamp, limit]) | ||
| } | ||
| kind: SBOM_CYCLONEDX_JSON |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "bomFormat": "CycloneDX", | ||
| "specVersion": "1.5", | ||
| "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79", | ||
| "version": 1, | ||
| "metadata": { | ||
| "timestamp": "2024-06-15T10:30:00Z", | ||
| "tools": [ | ||
| { | ||
| "vendor": "chainloop", | ||
| "name": "chainloop", | ||
| "version": "0.1.0" | ||
| } | ||
| ] | ||
| }, | ||
| "components": [ | ||
| { | ||
| "type": "library", | ||
| "bom-ref": "pkg:npm/express@4.18.0", | ||
| "name": "express", | ||
| "version": "4.18.0", | ||
| "purl": "pkg:npm/express@4.18.0" | ||
| } | ||
| ] | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.