mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat: get_policies: Way to obtain policy files and content (#267)
closes #254 Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
ee898e112e
commit
46e28b36f8
@@ -189,7 +189,6 @@ pub extern "C" fn regorus_engine_add_data_json(
|
||||
/// Get list of loaded Rego packages as JSON.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_packages
|
||||
/// * `data`: JSON encoded value to be used as policy data.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_engine_get_packages(engine: *mut RegorusEngine) -> RegorusResult {
|
||||
to_regorus_string_result(|| -> Result<String> {
|
||||
@@ -198,6 +197,16 @@ pub extern "C" fn regorus_engine_get_packages(engine: *mut RegorusEngine) -> Reg
|
||||
}())
|
||||
}
|
||||
|
||||
/// Get list of policies as JSON.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_policies
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_engine_get_policies(engine: *mut RegorusEngine) -> RegorusResult {
|
||||
to_regorus_string_result(|| -> Result<String> {
|
||||
to_ref(&engine)?.engine.get_policies_as_json()
|
||||
}())
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_engine_add_data_from_json_file(
|
||||
|
||||
@@ -82,6 +82,19 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("%s\n", output)
|
||||
|
||||
// Print packages
|
||||
if output, err = engine1.GetPackages(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("%s\n", output)
|
||||
|
||||
// Print policies
|
||||
if output, err = engine1.GetPolicies(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("%s\n", output)
|
||||
}
|
||||
|
||||
@@ -55,6 +55,25 @@ func (e *Engine) AddPolicyFromFile(path string) (string, error) {
|
||||
return C.GoString(result.output), nil
|
||||
}
|
||||
|
||||
func (e *Engine) GetPackages() (string, error) {
|
||||
result := C.regorus_engine_get_packages(e.e)
|
||||
defer C.regorus_result_drop(result)
|
||||
if result.status != C.RegorusStatusOk {
|
||||
return "", fmt.Errorf("%s", C.GoString(result.error_message))
|
||||
}
|
||||
return C.GoString(result.output), nil
|
||||
}
|
||||
|
||||
func (e *Engine) GetPolicies() (string, error) {
|
||||
result := C.regorus_engine_get_policies(e.e)
|
||||
defer C.regorus_result_drop(result)
|
||||
if result.status != C.RegorusStatusOk {
|
||||
return "", fmt.Errorf("%s", C.GoString(result.error_message))
|
||||
}
|
||||
return C.GoString(result.output), nil
|
||||
}
|
||||
|
||||
|
||||
func (e *Engine) AddDataJson(data string) error {
|
||||
data_c := C.CString(data)
|
||||
defer C.free(unsafe.Pointer(data_c))
|
||||
|
||||
@@ -31,6 +31,12 @@ public class Test {
|
||||
System.out.println(coverageJson);
|
||||
|
||||
System.out.println(engine.getCoverageReportPretty());
|
||||
|
||||
String packagesJson = engine.getPackages();
|
||||
System.out.println(packagesJson);
|
||||
|
||||
String policiesJson = engine.getPolicies();
|
||||
System.out.println(policiesJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,25 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeGetPackages(
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeGetPolicies(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
engine_ptr: jlong,
|
||||
) -> jstring {
|
||||
let res = throw_err(env, |env| {
|
||||
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
|
||||
let policies = engine.get_policies_as_json()?;
|
||||
let policies_json = env.new_string(&policies)?;
|
||||
Ok(policies_json.into_raw())
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(_) => JObject::null().into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeClearData(
|
||||
env: JNIEnv,
|
||||
|
||||
@@ -26,6 +26,7 @@ public class Engine implements AutoCloseable, Cloneable {
|
||||
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);
|
||||
private static native String nativeGetPolicies(long enginePtr);
|
||||
private static native void nativeClearData(long enginePtr);
|
||||
private static native void nativeAddDataJson(long enginePtr, String data);
|
||||
private static native void nativeAddDataJsonFromFile(long enginePtr, String path);
|
||||
@@ -96,6 +97,15 @@ public class Engine implements AutoCloseable, Cloneable {
|
||||
return nativeGetPackages(enginePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of loaded policies.
|
||||
*
|
||||
* @return List of Rego policies as a JSON array of sources.
|
||||
*/
|
||||
public String getPolicies() {
|
||||
return nativeGetPolicies(enginePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the data document.
|
||||
*/
|
||||
|
||||
@@ -184,10 +184,18 @@ impl Engine {
|
||||
|
||||
/// Get the list of packages defined by loaded policies.
|
||||
///
|
||||
pub fn get_packages(&mut self) -> Result<Vec<String>> {
|
||||
pub fn get_packages(&self) -> Result<Vec<String>> {
|
||||
self.engine.get_packages()
|
||||
}
|
||||
|
||||
/// Get the list of policies.
|
||||
///
|
||||
pub fn get_policies(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string_pretty(
|
||||
&self.engine.get_policies_as_json()?,
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Add policy data.
|
||||
///
|
||||
/// * `data`: Rego value. A Rego value is a number, bool, string, None
|
||||
|
||||
@@ -92,6 +92,20 @@ impl Engine {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_packages(&self) -> Result<Vec<String>, Error> {
|
||||
self.engine
|
||||
.borrow()
|
||||
.get_packages()
|
||||
.map_err(|e| Error::new(runtime_error(), format!("Failed to get packages: {e}")))
|
||||
}
|
||||
|
||||
fn get_policies(&self) -> Result<String, Error> {
|
||||
self.engine
|
||||
.borrow()
|
||||
.get_policies_as_json()
|
||||
.map_err(|e| Error::new(runtime_error(), format!("Failed to get policies: {e}")))
|
||||
}
|
||||
|
||||
fn set_input(&self, ruby_hash: magnus::RHash) -> Result<(), Error> {
|
||||
let input_value: regorus::Value = serde_magnus::deserialize(ruby_hash).map_err(|e| {
|
||||
Error::new(
|
||||
@@ -289,6 +303,8 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
||||
"add_policy_from_file",
|
||||
method!(Engine::add_policy_from_file, 1),
|
||||
)?;
|
||||
engine_class.define_method("get_packages", method!(Engine::get_packages, 0))?;
|
||||
engine_class.define_method("get_policies", method!(Engine::get_policies, 0))?;
|
||||
|
||||
// data operations
|
||||
engine_class.define_method("add_data", method!(Engine::add_data, 1))?;
|
||||
|
||||
@@ -72,6 +72,13 @@ impl Engine {
|
||||
self.engine.get_packages().map_err(error_to_jsvalue)
|
||||
}
|
||||
|
||||
/// Get the list of policies.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_policies
|
||||
pub fn getPolicies(&self) -> Result<String, JsValue> {
|
||||
self.engine.get_policies_as_json().map_err(error_to_jsvalue)
|
||||
}
|
||||
|
||||
/// Clear policy data.
|
||||
///
|
||||
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_data
|
||||
@@ -179,6 +186,7 @@ impl Engine {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::error_to_jsvalue;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_test::wasm_bindgen_test;
|
||||
|
||||
@@ -216,7 +224,7 @@ mod tests {
|
||||
assert_eq!(pkg, "data.test");
|
||||
|
||||
let results = engine.evalQuery("data".to_string())?;
|
||||
let r = regorus::Value::from_json_str(&results).map_err(crate::error_to_jsvalue)?;
|
||||
let r = regorus::Value::from_json_str(&results).map_err(error_to_jsvalue)?;
|
||||
|
||||
let v = &r["result"][0]["expressions"][0]["value"];
|
||||
|
||||
@@ -228,7 +236,7 @@ mod tests {
|
||||
|
||||
// Use eval_rule to perform same query.
|
||||
let v = engine.evalRule("data.test.message".to_owned())?;
|
||||
let v = regorus::Value::from_json_str(&v).map_err(crate::error_to_jsvalue)?;
|
||||
let v = regorus::Value::from_json_str(&v).map_err(error_to_jsvalue)?;
|
||||
|
||||
// Ensure that input and policy were evaluated.
|
||||
assert_eq!(v, regorus::Value::from("Hello"));
|
||||
@@ -246,7 +254,7 @@ mod tests {
|
||||
|
||||
// Test code coverage.
|
||||
let report = engine1.getCoverageReport()?;
|
||||
let r = regorus::Value::from_json_str(&report).map_err(crate::error_to_jsvalue)?;
|
||||
let r = regorus::Value::from_json_str(&report).map_err(error_to_jsvalue)?;
|
||||
|
||||
assert_eq!(
|
||||
r["files"][0]["covered"]
|
||||
@@ -258,6 +266,13 @@ mod tests {
|
||||
println!("{}", engine1.getCoverageReportPretty()?);
|
||||
|
||||
engine1.clearCoverageData();
|
||||
|
||||
let policies = engine1.getPolicies()?;
|
||||
let v = regorus::Value::from_json_str(&policies).map_err(error_to_jsvalue)?;
|
||||
assert_eq!(
|
||||
v[0]["path"].as_string().map_err(error_to_jsvalue)?.as_ref(),
|
||||
"hello.rego"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,66 @@ impl Engine {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get the list of policy files.
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// # let mut engine = Engine::new();
|
||||
///
|
||||
/// let pkg = engine.add_policy("hello.rego".to_string(), "package test".to_string())?;
|
||||
/// assert_eq!(pkg, "data.test");
|
||||
///
|
||||
/// let policies = engine.get_policies()?;
|
||||
///
|
||||
/// assert_eq!(policies[0].get_path(), "hello.rego");
|
||||
/// assert_eq!(policies[0].get_contents(), "package test");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn get_policies(&self) -> Result<Vec<Source>> {
|
||||
Ok(self
|
||||
.modules
|
||||
.iter()
|
||||
.map(|m| m.package.refr.span().source.clone())
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Get the list of policy files as a JSON object.
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// # let mut engine = Engine::new();
|
||||
///
|
||||
/// let pkg = engine.add_policy("hello.rego".to_string(), "package test".to_string())?;
|
||||
/// assert_eq!(pkg, "data.test");
|
||||
///
|
||||
/// let policies = engine.get_policies_as_json()?;
|
||||
///
|
||||
/// let v = Value::from_json_str(&policies)?;
|
||||
/// assert_eq!(v[0]["path"].as_string()?.as_ref(), "hello.rego");
|
||||
/// assert_eq!(v[0]["contents"].as_string()?.as_ref(), "package test");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn get_policies_as_json(&self) -> Result<String> {
|
||||
#[derive(Serialize)]
|
||||
struct Source<'a> {
|
||||
path: &'a String,
|
||||
contents: &'a String,
|
||||
}
|
||||
|
||||
let mut sources = vec![];
|
||||
for m in self.modules.iter() {
|
||||
let source = &m.package.refr.span().source;
|
||||
sources.push(Source {
|
||||
path: source.get_path(),
|
||||
contents: source.get_contents(),
|
||||
});
|
||||
}
|
||||
|
||||
serde_json::to_string_pretty(&sources).map_err(anyhow::Error::msg)
|
||||
}
|
||||
|
||||
/// Set the input document.
|
||||
///
|
||||
/// * `input`: Input documented. Typically this [Value] is constructed from JSON or YAML.
|
||||
|
||||
13
src/lexer.rs
13
src/lexer.rs
@@ -20,6 +20,7 @@ struct SourceInternal {
|
||||
pub lines: Vec<(u32, u32)>,
|
||||
}
|
||||
|
||||
/// A policy file.
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
||||
pub struct Source {
|
||||
@@ -27,6 +28,18 @@ pub struct Source {
|
||||
src: Rc<SourceInternal>,
|
||||
}
|
||||
|
||||
impl Source {
|
||||
/// The path associated with the policy file.
|
||||
pub fn get_path(&self) -> &String {
|
||||
&self.src.file
|
||||
}
|
||||
|
||||
/// The contents of the policy file.
|
||||
pub fn get_contents(&self) -> &String {
|
||||
&self.src.contents
|
||||
}
|
||||
}
|
||||
|
||||
impl cmp::Ord for Source {
|
||||
fn cmp(&self, other: &Source) -> cmp::Ordering {
|
||||
Rc::as_ptr(&self.src).cmp(&Rc::as_ptr(&other.src))
|
||||
|
||||
@@ -28,6 +28,7 @@ mod utils;
|
||||
mod value;
|
||||
|
||||
pub use engine::Engine;
|
||||
pub use lexer::Source;
|
||||
pub use value::Value;
|
||||
|
||||
#[cfg(feature = "arc")]
|
||||
|
||||
Reference in New Issue
Block a user