rego -- native OCaml Rego/OPA policy engine#
Pure OCaml implementation of the Rego policy language (Open Policy Agent). Evaluates Rego policies against JSON input/data documents.
Installation#
Install with opam:
$ opam install rego
If opam cannot find the package, it may not yet be released in the public
opam-repository. Add the overlay repository, then install it:
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install rego
Quick Start#
let engine = Rego.engine ()
let () =
match
Rego.add_policy engine ~name:"example.rego"
{|
package authz
default allow = false
allow { input.user == "admin" }
|}
with
| Ok () -> ()
| Error e -> failwith (Format.asprintf "%a" Rego.pp_error e)
let input =
Result.get_ok (Rego.Value.of_json_string {|{"user":"admin"}|})
let () =
match Rego.eval engine ~input "data.authz.allow" with
| Ok v -> assert (Rego.Value.equal v (Rego.Value.Bool true))
| Error e -> failwith (Format.asprintf "%a" Rego.pp_error e)
Features#
- Complete rules:
allow { body },x = value if { body } - Default rules:
default allow = false - Partial set rules:
s contains x if { body } - User-defined function rules:
double(x) = y if { y := x * 2 } - Iteration:
_wildcard, unbound index variables,some ... in,every ... in, and array/set/object comprehensions withinput/data modifiers- Path resolution:
input.a.b,data.pkg.rule(with longest-prefix package matching), same-package rule references - Expressions: literals, references, arithmetic, comparisons, set union
and intersection, unary minus,
:=and=unification assignment - Builtins:
count,sum,product,min,max,sort,startswith,endswith,contains,upper,lower,concat,split,replace,trim,trim_left,trim_right,trim_space,substring,indexof,sprintf,to_number,abs,ceil,floor,round,type_name,is_string,is_number,is_boolean,is_null,is_array,is_object,is_set,array.concat,array.slice,array.reverse,object.keys,object.values,object.get,print
API#
Rego.engine-- create a new policy engineRego.add_policy-- load a Rego policy module by nameRego.add_data/Rego.add_data_json-- set thedatadocumentRego.eval-- evaluate a query against the loaded policies and inputRego.eval_query-- evaluate a query as a body expression, returning the list of satisfying binding setsRego.parse_module/Rego.parse_expr-- parse Rego source to AST
OPA conformance#
test/opa_suite/ contains upstream test files pulled from OPA's own
conformance suite at
v1/test/cases/testdata/v0,
converted from YAML to JSON. They run as part of dune runtest, one
alcotest case per category plus an aggregate that reports the
pass/total count.
Known reasons for current failures, roughly ordered by impact:
regex.*,glob.*,json.patch,json.filter,time.*,crypto.*,net.cidr*,rego.metadata_*-- entire builtin families not yet implementedinas a free-standing membership operator (x in collection) -- parser supportssome x in c/every x in conly- Many OPA tests use
count(x, out),abs(x, out)style output-arg unification with compound patterns (e.g. array destructuring in the output slot) -- the simple variable case works, richer patterns don't - Numeric precision -- OCaml
floatcan't represent OPA's arbitrary-precision integers - Strict-mode errors, schema annotations, and metadata blocks
License#
ISC