Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ Conforma can verify test result attestations attached to images as in-toto state

== Rules Included

[#test_attestation__future_required_test_attestations_found]
=== link:#test_attestation__future_required_test_attestations_found[Future required test attestations were found]

Produce a warning when a test attestation that will be required in the future is not currently present. This allows teams to prepare for upcoming requirements without blocking current releases.

*Solution*: A test attestation that will be required at a future date is missing. Ensure the test is included before the effective date.

* Rule type: [rule-type-indicator warning]#WARNING#
* WARNING message: `%s is missing and will be required on %s`
* Code: `test_attestation.future_required_test_attestations_found`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L148[Source, window="_blank"]

[#test_attestation__no_erred_test_attestations]
=== link:#test_attestation__no_erred_test_attestations[No erred test attestations]

Expand All @@ -18,7 +30,7 @@ Produce a violation if any test result attestation has an erred result. The resu
* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Test attestation %q has an erred result`
* Code: `test_attestation.no_erred_test_attestations`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L236[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L264[Source, window="_blank"]

[#test_attestation__no_failed_informative_test_attestations]
=== link:#test_attestation__no_failed_informative_test_attestations[No failed informative test attestations]
Expand All @@ -30,7 +42,7 @@ Produce a warning if any informative test attestation has a failed result. Infor
* Rule type: [rule-type-indicator warning]#WARNING#
* WARNING message: `Informative test attestation %q has a failed result, failures: %s`
* Code: `test_attestation.no_failed_informative_test_attestations`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L88[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L89[Source, window="_blank"]

[#test_attestation__no_failed_tests]
=== link:#test_attestation__no_failed_tests[No failed test attestations]
Expand All @@ -42,7 +54,7 @@ Produce a violation if any non-informative test result attestation has a failed
* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Test attestation %q has a failed result, failures: %s`
* Code: `test_attestation.no_failed_tests`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L147[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L175[Source, window="_blank"]

[#test_attestation__no_skipped_test_attestations]
=== link:#test_attestation__no_skipped_test_attestations[No skipped test attestations]
Expand All @@ -54,7 +66,7 @@ Produce a violation if any test result attestation has a skipped result. A skipp
* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Test attestation %q has a skipped result`
* Code: `test_attestation.no_skipped_test_attestations`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L266[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L294[Source, window="_blank"]

[#test_attestation__no_test_warnings]
=== link:#test_attestation__no_test_warnings[No test attestation warnings]
Expand All @@ -66,7 +78,7 @@ Produce a warning if any test result attestation has a warned result. Warned tes
* Rule type: [rule-type-indicator warning]#WARNING#
* WARNING message: `Test attestation %q has warnings, warnings: %s`
* Code: `test_attestation.no_test_warnings`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L119[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L120[Source, window="_blank"]

[#test_attestation__test_result_known]
=== link:#test_attestation__test_result_known[No unsupported test attestation result values]
Expand All @@ -78,19 +90,43 @@ Ensure the result field of each test result attestation is a recognized value. V
* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Test attestation %q has an unsupported result value %q`
* Code: `test_attestation.test_result_known`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L179[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L207[Source, window="_blank"]

[#test_attestation__required_test_attestations_list_provided]
=== link:#test_attestation__required_test_attestations_list_provided[Required test attestations list was provided]

Confirm that when the "required-test-attestations" rule data key is provided, it resolves to a non-empty list of test names. This catches misconfiguration where the key is present but all entries have empty test lists or invalid effective_on dates.

*Solution*: Ensure the rule data contains a "required-test-attestations" key with at least one entry containing a non-empty "tests" array and a valid "effective_on" date.

* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Missing required required-test-attestations data`
* Code: `test_attestation.required_test_attestations_list_provided`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L388[Source, window="_blank"]

[#test_attestation__required_test_attestations_found]
=== link:#test_attestation__required_test_attestations_found[Required test attestations were found]

Produce a violation if a required test attestation is missing. Required test attestations are configured via the "required-test-attestations" rule data key with time-windowed entries. A test attestation is considered present when a verified test-result statement has predicate.configuration[0].name matching the required test name.

*Solution*: Ensure all required test attestations are produced and attached to the image. The required test attestation list is configurable via the "required-test-attestations" key in the rule data.
Comment thread
joejstuart marked this conversation as resolved.

* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Required test attestation %q is missing`
* Code: `test_attestation.required_test_attestations_found`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L358[Source, window="_blank"]

[#test_attestation__rule_data_provided]
=== link:#test_attestation__rule_data_provided[Rule data provided]

Confirm the expected rule data keys have been provided in the expected format. The keys are "supported_test_attestation_results", "failed_test_attestation_results", "erred_test_attestation_results", "skipped_test_attestation_results", "warned_test_attestation_results", and "informative_test_attestations".
Confirm the expected rule data keys have been provided in the expected format. The keys are "supported_test_attestation_results", "failed_test_attestation_results", "erred_test_attestation_results", "skipped_test_attestation_results", "warned_test_attestation_results", "informative_test_attestations", and "required-test-attestations".

*Solution*: If provided, ensure the rule data is in the expected format.

* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `%s`
* Code: `test_attestation.rule_data_provided`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L330[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L414[Source, window="_blank"]

[#test_attestation__test_data_found]
=== link:#test_attestation__test_data_found[Test attestation data includes result]
Expand All @@ -102,7 +138,7 @@ Each test result attestation must include a result field in its predicate. Verif
* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Test attestation %q is missing the required result field`
* Code: `test_attestation.test_data_found`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L209[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L237[Source, window="_blank"]

[#test_attestation__subject_mismatch]
=== link:#test_attestation__subject_mismatch[Test attestation subject matches image]
Expand All @@ -114,4 +150,4 @@ Verify that each test-result attestation's subject includes the digest of the im
* Rule type: [rule-type-indicator failure]#FAILURE#
* FAILURE message: `Test attestation %q subject does not match image digest %q`
* Code: `test_attestation.subject_mismatch`
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L298[Source, window="_blank"]
* https://github.com/conforma/policy/blob/{page-origin-refhash}/policy/release/test_attestation/test_attestation.rego#L326[Source, window="_blank"]
7 changes: 6 additions & 1 deletion antora/docs/modules/ROOT/pages/release_policy.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,15 @@ Rules included:
* xref:packages/release_tasks.adoc#tasks__required_tasks_list_provided[Tasks: Required tasks list was provided]
* xref:packages/release_tasks.adoc#tasks__successful_pipeline_tasks[Tasks: Successful pipeline tasks]
* xref:packages/release_tasks.adoc#tasks__unsupported[Tasks: Task version unsupported]
* xref:packages/release_test_attestation.adoc#test_attestation__future_required_test_attestations_found[Test attestation: Future required test attestations were found]
* xref:packages/release_test_attestation.adoc#test_attestation__no_erred_test_attestations[Test attestation: No erred test attestations]
* xref:packages/release_test_attestation.adoc#test_attestation__no_failed_informative_test_attestations[Test attestation: No failed informative test attestations]
* xref:packages/release_test_attestation.adoc#test_attestation__no_failed_tests[Test attestation: No failed test attestations]
* xref:packages/release_test_attestation.adoc#test_attestation__no_skipped_test_attestations[Test attestation: No skipped test attestations]
* xref:packages/release_test_attestation.adoc#test_attestation__no_test_warnings[Test attestation: No test attestation warnings]
* xref:packages/release_test_attestation.adoc#test_attestation__test_result_known[Test attestation: No unsupported test attestation result values]
* xref:packages/release_test_attestation.adoc#test_attestation__required_test_attestations_list_provided[Test attestation: Required test attestations list was provided]
* xref:packages/release_test_attestation.adoc#test_attestation__required_test_attestations_found[Test attestation: Required test attestations were found]
* xref:packages/release_test_attestation.adoc#test_attestation__rule_data_provided[Test attestation: Rule data provided]
* xref:packages/release_test_attestation.adoc#test_attestation__test_data_found[Test attestation: Test attestation data includes result]
* xref:packages/release_test_attestation.adoc#test_attestation__subject_mismatch[Test attestation: Test attestation subject matches image]
Expand Down Expand Up @@ -365,8 +368,8 @@ Rules included:
* xref:packages/release_git_branch.adoc#git_branch__git_branch[Git branch checks: Builds have a trusted target branch]
* xref:packages/release_github_certificate.adoc#github_certificate__gh_workflow_extensions[GitHub Certificate Checks: GitHub Workflow Certificate Extensions]
* xref:packages/release_github_certificate.adoc#github_certificate__gh_workflow_name[GitHub Certificate Checks: GitHub Workflow Name]
* xref:packages/release_github_certificate.adoc#github_certificate__gh_workflow_ref[GitHub Certificate Checks: GitHub Workflow Repository]
* xref:packages/release_github_certificate.adoc#github_certificate__gh_workflow_repository[GitHub Certificate Checks: GitHub Workflow Repository]
* xref:packages/release_github_certificate.adoc#github_certificate__gh_workflow_ref[GitHub Certificate Checks: GitHub Workflow Repository]
* xref:packages/release_github_certificate.adoc#github_certificate__gh_workflow_trigger[GitHub Certificate Checks: GitHub Workflow Trigger]
* xref:packages/release_github_certificate.adoc#github_certificate__rule_data_provided[GitHub Certificate Checks: Rule data provided]
* xref:packages/release_hermetic_task.adoc#hermetic_task__hermetic[Hermetic task: Task called with hermetic param set]
Expand Down Expand Up @@ -472,6 +475,8 @@ Rules included:
* xref:packages/release_test_attestation.adoc#test_attestation__no_failed_tests[Test attestation: No failed test attestations]
* xref:packages/release_test_attestation.adoc#test_attestation__no_skipped_test_attestations[Test attestation: No skipped test attestations]
* xref:packages/release_test_attestation.adoc#test_attestation__test_result_known[Test attestation: No unsupported test attestation result values]
* xref:packages/release_test_attestation.adoc#test_attestation__required_test_attestations_list_provided[Test attestation: Required test attestations list was provided]
* xref:packages/release_test_attestation.adoc#test_attestation__required_test_attestations_found[Test attestation: Required test attestations were found]
* xref:packages/release_test_attestation.adoc#test_attestation__rule_data_provided[Test attestation: Rule data provided]
* xref:packages/release_test_attestation.adoc#test_attestation__test_data_found[Test attestation: Test attestation data includes result]
* xref:packages/release_test_attestation.adoc#test_attestation__subject_mismatch[Test attestation: Test attestation subject matches image]
Expand Down
3 changes: 3 additions & 0 deletions antora/docs/modules/ROOT/partials/release_policy_nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,15 @@
**** xref:packages/release_test.adoc#test__test_data_found[Test data found]
**** xref:packages/release_test.adoc#test__test_results_found[Test data includes results key]
*** xref:packages/release_test_attestation.adoc[Test attestation]
**** xref:packages/release_test_attestation.adoc#test_attestation__future_required_test_attestations_found[Future required test attestations were found]
**** xref:packages/release_test_attestation.adoc#test_attestation__no_erred_test_attestations[No erred test attestations]
**** xref:packages/release_test_attestation.adoc#test_attestation__no_failed_informative_test_attestations[No failed informative test attestations]
**** xref:packages/release_test_attestation.adoc#test_attestation__no_failed_tests[No failed test attestations]
**** xref:packages/release_test_attestation.adoc#test_attestation__no_skipped_test_attestations[No skipped test attestations]
**** xref:packages/release_test_attestation.adoc#test_attestation__no_test_warnings[No test attestation warnings]
**** xref:packages/release_test_attestation.adoc#test_attestation__test_result_known[No unsupported test attestation result values]
**** xref:packages/release_test_attestation.adoc#test_attestation__required_test_attestations_list_provided[Required test attestations list was provided]
**** xref:packages/release_test_attestation.adoc#test_attestation__required_test_attestations_found[Required test attestations were found]
**** xref:packages/release_test_attestation.adoc#test_attestation__rule_data_provided[Rule data provided]
**** xref:packages/release_test_attestation.adoc#test_attestation__test_data_found[Test attestation data includes result]
**** xref:packages/release_test_attestation.adoc#test_attestation__subject_mismatch[Test attestation subject matches image]
Expand Down
48 changes: 48 additions & 0 deletions design/time-gated-rule-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Time-Gated Rule Data

Rule data entries with `effective_on` dates allow gradual rollout of policy requirements. The `ectime` library resolves which entry applies now (`most_current`) and which is newest regardless of date (`newest`). Several packages use this pattern: `required_tasks`, `test_attestation`, and their release-side counterparts.

## How do `most_current` and `newest` differ in failure behavior?

Comment thread
joejstuart marked this conversation as resolved.
`newest` sorts entries by `effective_on` as a string and picks the last one. It almost always succeeds for non-empty input — it doesn't parse or validate dates. `most_current` parses each `effective_on` with `time.parse_rfc3339_ns`, filters to entries not in the future, then calls `newest` on that filtered set. It is undefined when all entries are in the future.

This asymmetry matters: checking `not ectime.newest(data)` is almost never true when data exists, so it's not a useful guard on its own. The meaningful existence check is whether the resolution path produces an entry with the expected fields (e.g., `.tests` or `.tasks`).

## Why do consumer helpers need `default` values?

Rego's `not X in Y` requires `Y` to be defined. If `Y` is undefined, Rego tries to bind `Y` before evaluating the `in` expression, and the undefined binding causes the entire rule body to fail — `not` does not rescue it. This means helpers consumed by rules that use `in` or `some ... in` must always be defined.

Use `default _helper := []` (not `else := []`) to provide the fallback. `default` is the canonical Rego mechanism for ensuring a rule always has a value. `else := []` works but conflates "couldn't resolve" with "resolved to empty," making existence checks on the same helper unreliable.

## What is the pattern for adding new time-gated rule data?

Follow the separation used by `required_tasks` and `test_attestation`:

1. **Consumer helpers** — always defined via `default`, safe for `in` expressions:
```rego
default _current_required_items := []
_current_required_items := entry.items if {
entry := ectime.most_current(_rule_data)
}
```

2. **Existence checks** — undefined-based boolean helpers (no default/else) for deny/warn guards:
```rego
_resolved_required_items if {
ectime.most_current(_rule_data).items
}
_resolved_required_items if {
ectime.newest(_rule_data).items
}
```

3. **Deny rule** — checks data exists but resolution fails:
```rego
deny contains result if {
count(_rule_data) > 0
not _resolved_required_items
...
}
```

The boolean helper uses two rule bodies (OR): it's true if either current or newest resolves to an entry with the expected field. The deny fires only when data was provided but neither path produces a usable entry.
Loading
Loading