feat: Update to OPA v1.2.0 (#373)

Regorus now defaults to rego v1. `import rego.v1` is no longer needed.
Additionally, `future` keywords are automatically imported.

See
https://www.openpolicyagent.org/docs/latest/v0-upgrade/#changes-to-rego-in-opa-v10
to understand the differences between rego v1 and v0.

BREAKING CHANGE:

v0 style policies will error out by default. To enable v0 behavior, call engine.set_rego_v0(true) before
loading policies.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2025-03-10 11:56:01 -07:00
committed by GitHub
parent cbd772623a
commit c963e477a3
36 changed files with 244 additions and 91 deletions
+6 -1
View File
@@ -27,7 +27,7 @@ char* file_to_string(const char* file) {
// If regorus is built with custom-allocator, then provide implementation.
uint8_t* regorus_aligned_alloc(size_t alignment, size_t size) {
return aligned_alloc(alignment, size);
return (uint8_t*) aligned_alloc(alignment, size);
}
void regorus_free(uint8_t* ptr) {
@@ -41,6 +41,11 @@ int main() {
RegorusResult r;
char* buffer = NULL;
// Turn on rego v0 since policy uses v0.
r = regorus_engine_set_rego_v0(engine, true);
if (r.status != RegorusStatusOk)
goto error;
// Load policies.
r = regorus_engine_add_policy(engine, "framework.rego", (buffer = file_to_string("../../../tests/aci/framework.rego")));
free(buffer);
+5
View File
@@ -6,6 +6,11 @@ int main() {
RegorusEngine* engine = regorus_engine_new();
RegorusResult r;
// Turn on rego v0 since policy uses v0.
r = regorus_engine_set_rego_v0(engine, true);
if (r.status != RegorusStatusOk)
goto error;
// Load policies.
r = regorus_engine_add_policy_from_file(engine, "../../../tests/aci/framework.rego");
if (r.status != RegorusStatusOk)
+2
View File
@@ -6,6 +6,7 @@ void example()
// Create engine
regorus::Engine engine;
engine.set_rego_v0(true);
engine.set_enable_coverage(true);
// Add policies.
@@ -83,6 +84,7 @@ int main() {
// Create engine.
regorus::Engine engine;
engine.set_rego_v0(true);
// Load policies.
+3
View File
@@ -54,6 +54,9 @@ namespace regorus {
return std::unique_ptr<Engine>(new Engine(regorus_engine_clone(engine)));
}
Result set_rego_v0(bool enable) {
return Result(regorus_engine_set_rego_v0(engine, enable));
}
Result add_policy(const char* path, const char* policy) {
return Result(regorus_engine_add_policy(engine, path, policy));
+7
View File
@@ -62,6 +62,13 @@ namespace Microsoft.WindowsAzure.Regorus.IaaS
{
return Encoding.UTF8.GetBytes(s + char.MinValue);
}
public void SetRegoV0(bool enable)
{
unsafe
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_set_rego_v0(E, enable));
}
}
public void AddPolicy(string path, string rego)
{
+1
View File
@@ -23,6 +23,7 @@ var w = new Stopwatch();
w.Restart();
var engine = new Regorus.Engine();
engine.SetRegoV0(true);
w.Stop();
var newEngineTicks = w.ElapsedTicks;
+8
View File
@@ -51,6 +51,14 @@ namespace Regorus
}
}
public void SetRegoV0(bool enable)
{
unsafe
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_set_rego_v0(E, enable));
}
}
public string AddPolicyFromFile(string path)
{
var pathBytes = NullTerminatedUTF8Bytes(path);
+31 -9
View File
@@ -222,7 +222,7 @@ pub extern "C" fn regorus_engine_add_data_from_json_file(
/// Clear policy data.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_data
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_data
#[no_mangle]
pub extern "C" fn regorus_engine_clear_data(engine: *mut RegorusEngine) -> RegorusResult {
to_regorus_result(|| -> Result<()> {
@@ -233,7 +233,7 @@ pub extern "C" fn regorus_engine_clear_data(engine: *mut RegorusEngine) -> Regor
/// Set input.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_input
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_input
/// * `input`: JSON encoded value to be used as input to query.
#[no_mangle]
pub extern "C" fn regorus_engine_set_input_json(
@@ -264,7 +264,7 @@ pub extern "C" fn regorus_engine_set_input_from_json_file(
/// Evaluate query.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_query
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_query
/// * `query`: Rego expression to be evaluate.
#[no_mangle]
pub extern "C" fn regorus_engine_eval_query(
@@ -289,7 +289,7 @@ pub extern "C" fn regorus_engine_eval_query(
/// Evaluate specified rule.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_rule
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_rule
/// * `rule`: Path to the rule.
#[no_mangle]
pub extern "C" fn regorus_engine_eval_rule(
@@ -314,7 +314,7 @@ pub extern "C" fn regorus_engine_eval_rule(
/// Enable/disable coverage.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_enable_coverage
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_enable_coverage
/// * `enable`: Whether to enable or disable coverage.
#[no_mangle]
#[cfg(feature = "coverage")]
@@ -330,7 +330,7 @@ pub extern "C" fn regorus_engine_set_enable_coverage(
/// Get coverage report.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.get_coverage_report
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_coverage_report
#[no_mangle]
#[cfg(feature = "coverage")]
pub extern "C" fn regorus_engine_get_coverage_report(engine: *mut RegorusEngine) -> RegorusResult {
@@ -375,7 +375,7 @@ pub extern "C" fn regorus_engine_get_coverage_report_pretty(
/// Clear coverage data.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_coverage_data
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_coverage_data
#[no_mangle]
#[cfg(feature = "coverage")]
pub extern "C" fn regorus_engine_clear_coverage_data(engine: *mut RegorusEngine) -> RegorusResult {
@@ -387,7 +387,7 @@ pub extern "C" fn regorus_engine_clear_coverage_data(engine: *mut RegorusEngine)
/// Whether to gather output of print statements.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_gather_prints
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_gather_prints
/// * `enable`: Whether to enable or disable gathering print statements.
#[no_mangle]
pub extern "C" fn regorus_engine_set_gather_prints(
@@ -402,7 +402,7 @@ pub extern "C" fn regorus_engine_set_gather_prints(
/// Take all the gathered print statements.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.take_prints
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.take_prints
#[no_mangle]
pub extern "C" fn regorus_engine_take_prints(engine: *mut RegorusEngine) -> RegorusResult {
let output = || -> Result<String> {
@@ -437,6 +437,28 @@ pub extern "C" fn regorus_engine_get_ast_as_json(engine: *mut RegorusEngine) ->
}
}
/// Enable/disable rego v1.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_rego_v0
#[no_mangle]
pub extern "C" fn regorus_engine_set_rego_v0(
engine: *mut RegorusEngine,
enable: bool,
) -> RegorusResult {
let output = || -> Result<()> {
to_ref(&engine)?.engine.set_rego_v0(enable);
Ok(())
}();
match output {
Ok(()) => RegorusResult {
status: RegorusStatus::RegorusStatusOk,
output: std::ptr::null_mut(),
error_message: std::ptr::null_mut(),
},
Err(e) => to_regorus_result(Err(e)),
}
}
#[cfg(feature = "custom_allocator")]
extern "C" {
fn regorus_aligned_alloc(alignment: usize, size: usize) -> *mut u8;
+4 -1
View File
@@ -16,8 +16,11 @@ func main() {
// Create new engine
engine := regorus.NewEngine()
defer engine.Close()
elapsed1 := time.Since(t)
engine.SetRegoV0(true)
elapsed1 := time.Since(t)
t = time.Now()
// Add policies and data.
policies := []string{
+11
View File
@@ -28,6 +28,17 @@ func (e *Engine) Clone() *Engine {
return c
}
func (e *Engine) SetRegoV0(enable bool) (error) {
result := C.regorus_engine_set_rego_v0(e.e, C.bool(enable))
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return fmt.Errorf("%s", C.GoString(result.error_message))
}
return nil
}
func (e *Engine) AddPolicy(path string, rego string) (string, error) {
path_c := C.CString(path)
defer C.free(unsafe.Pointer(path_c))
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "regorus-java"
version = "0.2.2"
version = "0.3.0"
edition = "2021"
repository = "https://github.com/microsoft/regorus/bindings/java"
description = "Java bindings for Regorus - a fast, lightweight Rego interpreter written in Rust"
+23 -17
View File
@@ -4,39 +4,45 @@
import com.microsoft.regorus.Engine;
public class Test {
public static void main(String[] args) {
try (Engine engine = new Engine()) {
String pkg = engine.addPolicy(
"hello.rego",
"package test\nx=1\nmessage = concat(\", \", [input.message, data.message])"
"hello.rego",
"package test\nx=1\nmessage = concat(\", \", [input.message, data.message])"
);
System.out.println("Loaded package " + pkg);
System.out.println("Loaded package " + pkg);
engine.addDataJson("{\"message\":\"World!\"}");
engine.setInputJson("{\"message\":\"Hello\"}");
// Evaluate query.
String resJson = engine.evalQuery("data.test.message");
// Evaluate query.
String resJson = engine.evalQuery("data.test.message");
System.out.println(resJson);
// Enable coverage.
engine.setEnableCoverage(true);
// Enable coverage.
engine.setEnableCoverage(true);
// Evaluate rule.
String valueJson = engine.evalRule("data.test.message");
// Evaluate rule.
String valueJson = engine.evalRule("data.test.message");
System.out.println(valueJson);
String coverageJson = engine.getCoverageReport();
System.out.println(coverageJson);
String coverageJson = engine.getCoverageReport();
System.out.println(coverageJson);
System.out.println(engine.getCoverageReportPretty());
System.out.println(engine.getCoverageReportPretty());
String packagesJson = engine.getPackages();
System.out.println(packagesJson);
String packagesJson = engine.getPackages();
System.out.println(packagesJson);
String policiesJson = engine.getPolicies();
System.out.println(policiesJson);
String policiesJson = engine.getPolicies();
System.out.println(policiesJson);
engine.setRegoV0(true);
engine.addPolicy(
"world.rego",
"package world\nx { true }"
);
}
}
}
+14
View File
@@ -28,6 +28,20 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeClone(
Box::into_raw(Box::new(c)) as jlong
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeSetRegoV0(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
enable: bool,
) {
let _ = throw_err(env, |_env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
engine.set_rego_v0(enable);
Ok(())
});
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeAddPolicy(
env: JNIEnv,
@@ -8,10 +8,8 @@ package com.microsoft.regorus;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.atomic.AtomicReference;
/**
* Regorus Engine.
@@ -23,6 +21,7 @@ public class Engine implements AutoCloseable, Cloneable {
// if you update the native API.
private static native long nativeNewEngine();
private static native long nativeClone(long enginePtr);
private static native void nativeSetRegoV0(long enginePtr, boolean enable);
private static native String nativeAddPolicy(long enginePtr, String path, String rego);
private static native String nativeAddPolicyFromFile(long enginePtr, String path);
private static native String nativeGetPackages(long enginePtr);
@@ -55,7 +54,7 @@ public class Engine implements AutoCloseable, Cloneable {
Engine(long ptr) {
enginePtr = ptr;
enginePtr = ptr;
}
/**
@@ -65,6 +64,16 @@ public class Engine implements AutoCloseable, Cloneable {
return new Engine(nativeClone(enginePtr));
}
/**
* Enable/disable Rego v0.
*
* @param enable Whether to enable v0 or not.
*
*/
public void setRegoV0(boolean enable) {
nativeSetRegoV0(enginePtr, enable);
}
/**
* Adds an inline Rego policy.
*
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "regoruspy"
version = "0.2.2"
version = "0.3.0"
edition = "2021"
repository = "https://github.com/microsoft/regorus/bindings/python"
description = "Python bindings for Regorus - a fast, lightweight Rego interpreter written in Rust"
+9
View File
@@ -168,6 +168,15 @@ impl Engine {
}
}
/// Turn on rego v0.
///
/// Regorus now defaults to v1.
///
/// * `enable`: Whether to enable/disable v0.
pub fn set_rego_v0(&mut self, enable: bool) {
self.engine.set_rego_v0(enable)
}
/// Add a policy
///
/// The policy is parsed into AST.
+2
View File
@@ -6,6 +6,8 @@ import regorus
# Create engine
engine = regorus.Engine()
engine.set_rego_v0(True)
# Load policies
pkg = engine.add_policy_from_file('../../tests/aci/framework.rego')
print(' Loaded package %s' % pkg)
+1 -1
View File
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
regorusrb (0.2.3)
regorusrb (0.3.0)
rb_sys (~> 0.9.111)
GEM
+3
View File
@@ -43,6 +43,9 @@ require "regorus"
engine = Regorus::Engine.new
# Policy is old-style.
engine.set_rego_v0(true)
engine.add_policy_from_file('../../tests/aci/framework.rego')
engine.add_policy_from_file('../../tests/aci/api.rego')
engine.add_policy_from_file('../../tests/aci/policy.rego')
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "regorusrb"
version = "0.2.3"
version = "0.3.0"
edition = "2024"
description = "Ruby bindings for Regorus - a fast, lightweight Rego interpreter written in Rust"
publish = false
+8
View File
@@ -36,6 +36,11 @@ impl Engine {
}
}
fn set_rego_v0(&self, enable: bool) -> Result<(), Error> {
self.engine.borrow_mut().set_rego_v0(enable);
Ok(())
}
fn add_policy(&self, path: String, rego: String) -> Result<String, Error> {
self.engine
.borrow_mut()
@@ -297,6 +302,9 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
// defines <, <=, >, >=, and == based on <=>
engine_class.include_module(module::comparable())?;
// rego language configuration
engine_class.define_method("set_rego_v0", method!(Engine::set_rego_v0, 1))?;
// policy operations
engine_class.define_method("add_policy", method!(Engine::add_policy, 2))?;
engine_class.define_method(
+1 -1
View File
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module Regorus
VERSION = "0.2.3"
VERSION = "0.3.0"
end
+4 -4
View File
@@ -17,11 +17,11 @@ class TestRegorus < Minitest::Test
def example_policy
<<~REGO
package regorus_test
is_manager {
is_manager if {
input.name == data.managers[_]
}
is_employee {
is_employee if {
input.name == data.employees[_]
}
@@ -29,11 +29,11 @@ class TestRegorus < Minitest::Test
default is_manager_bool = false
default is_employee_bool = false
is_manager_bool {
is_manager_bool if {
is_manager
}
is_employee_bool {
is_employee_bool if {
is_employee
}
REGO
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "regorusjs"
version = "0.2.2"
version = "0.3.0"
edition = "2021"
repository = "https://github.com/microsoft/regorus/bindings/wasm"
description = "WASM bindings for Regorus - a fast, lightweight Rego interpreter written in Rust"
+9
View File
@@ -45,6 +45,15 @@ impl Engine {
}
}
/// Turn on rego v0.
///
/// Regorus defaults to rego v1.
///
/// * `enable`: Whether to enable or disable rego v0.
pub fn setRegoV0(&mut self, enable: bool) {
self.engine.set_rego_v0(enable)
}
/// Add a policy
///
/// The policy is parsed into AST.