Policy authoring.
Policy is Open Policy Agent Rego. Author it by hand, or compose rules, AND/OR groups and an action in the visual builder and let it compile to Rego you can review.
Anatomy of a policy
A policy receives a structured input — the finding, its entity context, reachability and exposure, the environment — and returns a decision. The evaluator runs OPA as a subprocess over that input and parses the result. There is no network access during evaluation.
# policy: block reachable critical dependencies on internet-facing workloads
package securityvault.gate
default allow := false
allow if {
count(deny) == 0
}
deny[msg] if {
f := input.findings[_]
f.severity == "critical"
f.reachability.verdict == "reachable"
input.subject.exposed == true
msg := sprintf("reachable critical %s on exposed workload", [f.id])
}The visual builder
For teams that do not write Rego, the builder models a policy as PolicyRule (field, operator, value) → PolicyGroup (AND / OR) → PolicySpec (groups, action, metadata) and renders valid Rego. Field paths are allow-listed — each segment must be an identifier — so a rule can never break out of the generated expression. The generated Rego is stored and shown, so engineers review exactly what will run.
Fail closed
Any evaluator error — invalid policy, timeout, missing input — yields DENY with reasonOPA_EVALUATION_FAILED. There is no configuration that turns an evaluation error into an allow.
Signed decisions and the audit chain
Control decisions are signed with Ed25519 over a canonical, sorted-key payload: control_id, decision, framework_control_id, input_hash, organization_id, public_key_fingerprint, schema_version, timestamp. The private key is held by the evaluation service; the public half can be handed to auditors. The audit log appends each event with the HMAC of its predecessor.
Exceptions and overrides
Exceptions carry an owner, an expiry, an approver chain and optional dual control. Gate overrides (break-glass) require an authorised principal and are recorded as audited events; they never rewrite the original decision.
Patterns we recommend
- Gate on reachable and exposed, not on raw severity alone — the ontology gives you both.
- Start policies in advisory mode on pull requests; enforce once the false-positive rate is understood.
- Prefer one policy per gate with named deny messages over a single monolithic policy.
- Treat a rising count of
OPA_EVALUATION_FAILEDas an incident: it means gates are denying for the wrong reason.