|
| 1 | +# Policy Development Quickstart |
| 2 | + |
| 3 | +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. |
| 4 | + |
| 5 | +## Documentation References |
| 6 | + |
| 7 | +- **CLI Reference**: [chainloop policy develop commands](https://docs.chainloop.dev/command-line-reference/cli-reference#chainloop-policy) |
| 8 | +- **Policy Concepts**: [Understanding Chainloop Policies](https://docs.chainloop.dev/concepts/policies) |
| 9 | +- **Custom Policy Guide**: [Writing Custom Policies](https://docs.chainloop.dev/guides/custom-policies) |
| 10 | +- **Material Types**: [Available Material Types](https://docs.chainloop.dev/concepts/material-types#material-types) |
| 11 | + |
| 12 | +## Quick Test |
| 13 | + |
| 14 | +### Step 1: Download the Example Files |
| 15 | + |
| 16 | +```bash |
| 17 | +# Download the policy and sample materials |
| 18 | +curl -O https://raw.githubusercontent.com/chainloop-dev/chainloop/refs/heads/main/docs/examples/policies/quickstart/cdx-fresh.yaml |
| 19 | +curl -O https://raw.githubusercontent.com/chainloop-dev/chainloop/refs/heads/main/docs/examples/policies/quickstart/cdx-old.json |
| 20 | +curl -O https://raw.githubusercontent.com/chainloop-dev/chainloop/refs/heads/main/docs/examples/policies/quickstart/cdx-fresh.json |
| 21 | +``` |
| 22 | + |
| 23 | +### Step 2: Lint the Policy |
| 24 | + |
| 25 | +Check your policy's structure and Rego syntax. Run it with `--format` flag to fix all formatting inconsistencies. |
| 26 | + |
| 27 | +```bash |
| 28 | +chainloop policy develop lint --policy cdx-fresh.yaml --format |
| 29 | +``` |
| 30 | + |
| 31 | +**Expected output:** |
| 32 | +``` |
| 33 | +INF policy is valid! |
| 34 | +``` |
| 35 | + |
| 36 | +### Step 3: Evaluate the Policy |
| 37 | + |
| 38 | +Use your SBOM CycloneDX material to test your policy logic. |
| 39 | + |
| 40 | +```bash |
| 41 | +# Test with old SBOM (should fail) |
| 42 | +chainloop policy develop eval --policy cdx-fresh.yaml --material cdx-old.json --kind SBOM_CYCLONEDX_JSON |
| 43 | + |
| 44 | +# Test with fresh SBOM (should pass) |
| 45 | +chainloop policy develop eval --policy cdx-fresh.yaml --material cdx-fresh.json --kind SBOM_CYCLONEDX_JSON |
| 46 | +``` |
| 47 | + |
| 48 | +**Expected Results:** |
| 49 | + |
| 50 | +**Old SBOM (should fail):** |
| 51 | +``` |
| 52 | +INF - cdx-fresh: SBOM created at: 2024-06-15T10:30:00Z which is too old (freshness limit set to 30 days) |
| 53 | +INF policy evaluation failed |
| 54 | +``` |
| 55 | + |
| 56 | +**Fresh SBOM (should pass):** |
| 57 | +``` |
| 58 | +INF policy evaluation passed |
| 59 | +``` |
| 60 | + |
| 61 | +## Create Your Own Policy |
| 62 | + |
| 63 | +### Step 1: Initialize a Policy Template |
| 64 | + |
| 65 | +Create a new policy with the embedded format (single YAML file): |
| 66 | + |
| 67 | +```bash |
| 68 | +chainloop policy develop init --embedded --name my-policy --description "My custom policy description" |
| 69 | +``` |
| 70 | + |
| 71 | +**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. |
| 72 | + |
| 73 | +### Step 2: Write Your Policy Rules |
| 74 | + |
| 75 | +Edit the generated YAML file and replace the placeholder code in the `embedded` section with your Rego logic. |
| 76 | + |
| 77 | +**Important**: Remove the `default violations := []` line to avoid conflicts with your `violations contains msg if` rules. |
| 78 | + |
| 79 | +### Step 3: Test Your Policy |
| 80 | + |
| 81 | +Follow steps 2-3 above with your own policy and materials. |
| 82 | + |
| 83 | +## Policy Logic Explained |
| 84 | + |
| 85 | +The SBOM freshness policy calculates a 30-day threshold in nanoseconds and compares it against the SBOM's `metadata.timestamp` field: |
| 86 | + |
| 87 | +1. **Converts 30 days to nanoseconds**: `30 * 24 * 60 * 60 * 1000 * 1000 * 1000` |
| 88 | +2. **Parses the SBOM timestamp** using `time.parse_rfc3339_ns()` |
| 89 | +3. **Checks if current time minus (SBOM time + threshold) is positive** |
| 90 | +4. **If positive, the SBOM is too old** and a violation is raised |
| 91 | + |
| 92 | +## Available Material Types |
| 93 | + |
| 94 | +For the complete list of supported material types, see the [Material Types documentation](https://docs.chainloop.dev/concepts/material-types#material-types). |
| 95 | + |
| 96 | +Common material types for the `--kind` parameter: |
| 97 | + |
| 98 | +- `SBOM_CYCLONEDX_JSON` - CycloneDX SBOM files |
| 99 | +- `SBOM_SPDX_JSON` - SPDX SBOM files |
| 100 | +- `CONTAINER_IMAGE` - Container images |
| 101 | +- `ATTESTATION` - Generic attestations |
| 102 | +- `SARIF` - SARIF security scan results |
| 103 | +- `SLSA_PROVENANCE` - SLSA provenance attestations |
| 104 | + |
| 105 | +Run `chainloop policy develop eval --help` for the complete list. |
| 106 | + |
| 107 | +## Common Issues |
| 108 | + |
| 109 | +1. **Rego type conflicts**: Remove `default violations := []` when using `violations contains msg if` rules |
| 110 | +2. **Missing material kind**: Always specify `--kind` parameter in eval command |
| 111 | +3. **File naming**: Policy files are named based on the `--name` parameter, not always `policy.yaml` |
| 112 | +4. **Time calculations**: Use nanoseconds for time comparisons in Rego policies |
| 113 | + |
| 114 | +## Next Steps |
| 115 | + |
| 116 | +Once you've mastered the basics: |
| 117 | + |
| 118 | +1. Explore more complex examples in the [policy examples]](../) directory |
| 119 | +2. Learn about policy inputs and annotations |
| 120 | +3. Practice with different material types |
| 121 | +4. Deploy policies to your Chainloop workflows |
0 commit comments