Explainable policies that run on Open Policy Agent and Rego.
ergo is an open source language for writing explainable policies. Instead of a binary result, every decision returns an audit report of what was checked, and why it passed or failed.
ergo the policy
requirements:
prod_deploy:
subject_type: deployment
from: [deployments]
id: [id]
applies_to:
is_prod:
op: equals
path: [environment]
value: prod
checks:
approved:
description: Someone approved the deployment
op: non_empty_string
path: [approved_by]ergo the evaluation, reading this input
{
"deployments": [
{"id": "d-1", "environment": "prod",
"approved_by": "alice"},
{"id": "d-2", "environment": "prod"},
{"id": "d-3", "environment": "staging"}
]
}Three deployments. d-2 has no approved_by field at all, and d-3 is in staging.
ergo the report
d-3 is out of scope. d-2 was never approved… and the report says so.
ergo the policy
requirements:
peer_reviewed:
subject_type: pull request
from: [pull_requests, {each_as: pr}]
id: [number]
checks:
peer:
description: Someone other than the author approved it
op: any
path: [approvers]
check:
op: compare
left: [username]
right: [$pr, author]
cmp: neergo the evaluation, reading this input
{
"pull_requests": [
{"number": 1, "author": "ann",
"approvers": [{"username": "ann"}, {"username": "bob"}]},
{"number": 2, "author": "bob",
"approvers": [{"username": "bob"}]},
{"number": 3,
"approvers": [{"username": "bob"}]}
]
}Three pull requests. PR 2 was approved only by its author, and PR 3 has no author recorded.
ergo the report
approvers: ann, bobtruesatisfied
approvers: bobfalsevalue
approvers: bobfalseabsent
PR 2 was only approved by its author. PR 3 has no author recorded. Different problems, different fixes.
A decision nobody can inspect
isn't evidence.
With Rego you can block a deployment, but you can't show later why. When you write policies with ergo you have records of why decisions were made.
In regulated settings, someone else has to be able to check that a policy behaved as it should. A yes or no can't be validated. You don't just tell the auditor the decision. You hand over the workings.
Rego provides decisions
{
"allow": false
}Useful. But why was it false?
With ergo you get explanations
subject check value read passed cause
d-1 approved approved_by = "alice" true satisfied
d-2 approved approved_by = null false absent
d-3 $applies environment = "staging" false value (out of scope, recorded)Same decision. Now you can see why.
Write the policy.
Not the sorcery.
Defined in YAML or Rego
Write the requirement as a YAML file or as a Rego object. ergo reads both the same way and gives the same report.
- 1
Define the subjects
subject_type,fromandidsay what the subjects are and where to find them. - 2
Filter the scope
applies_tokeeps only the subjects this requirement is about. The rest are recorded, not dropped. - 3
Test the values
checksare the rules each subject must pass. ergo does the looping, the evaluation and the report.
# policy/requirements.yaml
requirements:
prod_deploy:
subject_type: deployment
from: [deployments]
id: [id]
applies_to:
is_prod:
op: equals
path: [environment]
value: prod
checks:
approved:
description: Someone approved the deployment
op: non_empty_string
path: [approved_by]One report format.
Every policy.
A deployment policy. A code-review policy. A vulnerability policy. Different checks, same evidence: one row per subject and check. Passing and failing rows have the same fields.
- requirement
Which requirement produced the row.
- subject
The thing that was judged, with its type and id.
- check
The rule that ran.
- inputs
The values the check actually read.
- passed
The result. Always
trueorfalse. - cause
Why it reached that result.
Same policy + same input = the same report, byte for byte. Hash it. Diff it. Store it.
- Nothing disappears.
- Nothing is implied.
- Everything is reproducible.
- Everything has a reason.
OPA is the engine.
ergo is a rego library.
ergo doesn't replace OPA. Copy a single rego file into your policies. The policy is expressed as YAML, JSON or rego and ergo provides a single evaluation and reporting model.
- inputs
- inputdeployments.json
- policyrequirements.yaml
- library ergo.rego
-
evaluation
- engineOPA 1.19
- outputs
- decisioncompliant
- evidence report
Auditor says why
Computer says ergo
Learn how to write self-explaining automated policies in this tutorial:
One file. No lock-in.
- 01
Copy the library
Copy
ergo.regonext to your policies. That's the install.policy/ ergo.rego - 02
Write a requirement
Say what you're judging, what's in scope and what must hold.
report := ergo.report(input, data.requirements) - 03
Read the report
Ask OPA for the report, or just the violations.
opa eval -d policy -i deployments.json \ 'data.deploy.report'
ergo /ˈɜː.ɡəʊ/
Therefore. As a result. A conclusion that comes with its premises.
Not computer says no. Here is the decision, and here is what produced it.