ワンクリックで
writing-rego-policies
// Use when writing, modifying, or reviewing OPA/conftest Rego policies. Covers package naming, rule prefixes (violation_ and warn_), conftest namespaces, violation object structures, imports, and unit test patterns.
// Use when writing, modifying, or reviewing OPA/conftest Rego policies. Covers package naming, rule prefixes (violation_ and warn_), conftest namespaces, violation object structures, imports, and unit test patterns.
Use when adding new tools, binaries, or packages to the konflux-test container image. Covers artifacts.lock.yaml (generic binaries), rpms.in.yaml (system packages), multi-architecture support, and hermetic build constraints.
Use when CI checks fail unexpectedly, when preparing code for CI, or when encountering non-obvious build and pipeline behavior. Covers hermetic builds, Tekton pipelines, multi-arch, GitHub Actions checks, and integration test structure.
Use when preparing a pull request for review or before pushing. Checklist of commit conventions, Rego policy tests at 100% coverage, BATS tests, code quality checks, and CI check requirements.
Use when running OPA policy unit tests, BATS bash tests, shellcheck, hadolint, or conftest integration tests locally. Covers test commands, coverage requirements, test data, and prerequisites.
Use when adding or modifying bash utility functions in test/utils.sh. Covers naming conventions, function structure, BATS tests, mock patterns for external tools, TEST_OUTPUT format, and shellcheck compliance.
| name | writing-rego-policies |
| description | Use when writing, modifying, or reviewing OPA/conftest Rego policies. Covers package naming, rule prefixes (violation_ and warn_), conftest namespaces, violation object structures, imports, and unit test patterns. |
Policies in policies/{scanner}/ validate structured outputs from Tekton security scanners using OPA and conftest. Each policy is a Rego package that generates violations or warnings based on input data from scanners like Clair, ClamAV, PickleScan, Roxctl, and RHTPA.
| Item | Convention |
|---|---|
| Policy location | policies/{scanner}/{check-name}.rego |
| Test location | unittests/test_{scanner}/{check-name}_test.rego |
| Test data | unittests/test_data/{scanner}.json or .yaml |
| Package names | required_checks, optional_checks, or fbc_checks |
| Rule prefixes | violation_* (failures), warn_* (warnings) |
| Conftest invocation | conftest test ... --namespace required_checks |
Policies use three package names, selected via --namespace flag:
| Package | Namespace flag | Purpose | Example |
|---|---|---|---|
required_checks | --namespace required_checks | Blocking policies, must pass | clair, roxctl, picklescan, image/required-labels |
optional_checks | --namespace optional_checks | Advisory warnings | image/inherited-labels, image/optional-labels |
fbc_checks | --namespace fbc_checks | FBC (File-Based Catalog) specific | image/fbc-labels |
A single .rego file contains exactly ONE package name.
| Prefix | Conftest result | Use when |
|---|---|---|
violation_ | Failure (blocks image) | Check must pass for image acceptance (most policies) |
warn_ | Warning (informational) | Check is advisory and doesn't block |
deny_ | Failure | Alternative prefix (not used in current policies) |
Rules must return a LIST (list comprehension [{...} | ...]), never a single object.
Structures vary by policy type:
[{"msg": msg, "vulnerabilities_number": vulns_num, "details": {"name": name, "description": description, "url": url}}]
[{"msg": msg, "details": {"name": name, "description": description, "url": url}}]
(No vulnerabilities_number field)
[{"msg": msg, "details": {"filename": filename, "virname": virname, "description": description}}]
(ClamAV); or {"filename": filename, "finding": finding} (PickleScan)
[{"msg": msg, "discrepancies_number": disc_num, "details": {"name": name, "description": description, "url": url}}]
Vulnerability policies typically define:
get_patched_vulnerabilities(input_data, severity) := vulnerabilities if { ... }
get_unpatched_vulnerabilities(input_data, severity) := vulnerabilities if { ... }
count_vulnerabilities(vulnerabilities) := cnt if { ... }
generate_description(vulnerabilities) := dsc if { ... }
Then use these in rule definitions. See policies/clair/vulnerabilities-check.rego for full pattern.
NOT all policies use imports. Add imports only when needed:
| Import | Use when |
|---|---|
import future.keywords.if | Using if keyword in rule definitions |
import future.keywords.in | Using in operator for membership checks |
import data as base_image | Accessing other data packages (rare) |
Label/image policies typically have no imports.
Use default to safely return empty arrays when data is absent:
default warn_critical_vulnerabilities := []
Only used in policies/rhtpa/vulnerabilities-check.rego.
Same package as policy, in unittests/test_{scanner}/{check-name}_test.rego:
package required_checks
import data.clair as clair
import future.keywords.if
test_warn_critical_vulnerabilities if {
result := warn_critical_vulnerabilities with input as clair
result[_].details.name == "clair_critical_vulnerabilities"
result[_].vulnerabilities_number == 1
}
Patterns:
import data.{fixture_name} as {alias}test_{rule_name}with input as fixture_alias.details.name, .vulnerabilities_number, .msgrule_name == [] with input as clean_data| Mistake | Fix |
|---|---|
| Wrong package name | Must match conftest --namespace flag exactly |
| Returning single object instead of list | Rules must be list comprehensions: [{...} | ...] |
| Wrong detail object keys | Use correct keys for policy type (see structures above) |
| Test data import wrong | File unittests/test_data/clair.json → import data.clair as clair |
| Missing test for empty input | Add negative test: rule == [] with input as empty_data |
Using if without importing | Add import future.keywords.if |