Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ bindings/*/target

# C# build folders
**bin
**obj
**obj

# Visual Studio folders
**/*.vs
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ default = ["full-opa", "arc"]

arc = ["scientific/arc"]
ast = []
azure_policy = []
base64 = ["dep:data-encoding"]
base64url = ["dep:data-encoding"]
coverage = []
Expand Down
39 changes: 39 additions & 0 deletions bindings/csharp/Regorus.Tests/RegorusTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,43 @@

Assert.IsTrue(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(result!)), $"Actual: {result}");
}

[TestMethod]
public void GetPolicyPackageNames_succeeds()
{
using var engine = new Engine();
engine.AddPolicy(
"test.rego",
"package test\nx = 1\nmessage = `Hello`");

engine.AddPolicy(
"test.rego",
"package test.nested.name\nx = 1\nmessage = `Hello`");

var result = engine.GetPolicyPackageNames();

var packageNames = JsonNode.Parse(result!);

Assert.AreEqual("test", packageNames![0]["package_name"].ToString());

Check warning on line 193 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 193 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 193 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.

Check warning on line 193 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.
Assert.AreEqual("test.nested.name", packageNames![1]["package_name"].ToString());

Check warning on line 194 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 194 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 194 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.

Check warning on line 194 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.
}

[TestMethod]
public void GetPolicyParameters_succeeds()
{
using var engine = new Engine();
engine.AddPolicy(
"test.rego",
"package test\n default parameters.a = 5\nparameters.b = 10\nx = 1\nmessage = `Hello`");

var result = engine.GetPolicyParameters();

var parameters = JsonNode.Parse(result!);

Assert.AreEqual(1, parameters![0]["parameters"].AsArray().Count);

Check warning on line 209 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 209 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 209 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.

Check warning on line 209 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.
Assert.AreEqual(1, parameters![0]["modifiers"].AsArray().Count);

Check warning on line 210 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 210 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 210 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.

Check warning on line 210 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.

Assert.AreEqual("a", parameters![0]["parameters"][0]["name"].ToString());

Check warning on line 212 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 212 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-unknown-linux-gnu)

Dereference of a possibly null reference.

Check warning on line 212 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.

Check warning on line 212 in bindings/csharp/Regorus.Tests/RegorusTests.cs

View workflow job for this annotation

GitHub Actions / Test Regorus Nuget: (x86_64-pc-windows-msvc)

Dereference of a possibly null reference.
Assert.AreEqual("b", parameters![0]["modifiers"][0]["name"].ToString());
}
}
10 changes: 10 additions & 0 deletions bindings/csharp/Regorus/Regorus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ public void SetGatherPrints(bool enable)
return CheckAndDropResult(Regorus.Internal.API.regorus_engine_get_ast_as_json(E));
}

public string? GetPolicyPackageNames()
{
return CheckAndDropResult(Regorus.Internal.API.regorus_engine_get_policy_package_names(E));
}

public string? GetPolicyParameters()
{
return CheckAndDropResult(Regorus.Internal.API.regorus_engine_get_policy_parameters(E));
}

string? StringFromUTF8(IntPtr ptr)
{

Expand Down
16 changes: 16 additions & 0 deletions bindings/csharp/Regorus/RegorusFFI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,22 @@ internal static unsafe partial class API
[DllImport(__DllName, EntryPoint = "regorus_engine_get_ast_as_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern RegorusResult regorus_engine_get_ast_as_json(RegorusEngine* engine);

/// <summary>
/// Gets the package names of policies added to the engine.
///
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Engine.html#method.get_policy_package_names
/// </summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_get_policy_package_names", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern RegorusResult regorus_engine_get_policy_package_names(RegorusEngine* engine);

/// <summary>
/// Gets the parameters defined in each policy added to the engine
///
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Engine.html#method.get_policy_parameters
/// </summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_get_policy_parameters", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern RegorusResult regorus_engine_get_policy_parameters(RegorusEngine* engine);

/// <summary>
/// Enable/disable rego v1.
///
Expand Down
2 changes: 1 addition & 1 deletion bindings/csharp/global.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
},
"sdk": {
"allowPrerelease": false,
"version": "8.0.408",
"version": "8.0.412",
"rollForward": "disable"
}
}
3 changes: 2 additions & 1 deletion bindings/ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ lto = true
codegen-units = 1

[features]
default = ["ast", "std", "coverage", "regorus/arc", "regorus/full-opa"]
default = ["ast", "azure_policy", "std", "coverage", "regorus/arc", "regorus/full-opa"]
ast = ["regorus/ast"]
azure_policy = ["regorus/azure_policy"]
std = ["regorus/std"]
coverage = ["regorus/coverage"]
custom_allocator = []
Expand Down
34 changes: 34 additions & 0 deletions bindings/ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,40 @@ pub extern "C" fn regorus_engine_get_ast_as_json(engine: *mut RegorusEngine) ->
}
}

/// Gets the package names defined in each policy added to the engine.
///
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Engine.html#method.get_policy_package_names
#[no_mangle]
#[cfg(feature = "azure_policy")]
pub extern "C" fn regorus_engine_get_policy_package_names(engine: *mut RegorusEngine) -> RegorusResult {
let output = || -> Result<String> { serde_json::to_string_pretty(&to_ref(engine)?.engine.get_policy_package_names()?).map_err(anyhow::Error::msg) }();
match output {
Ok(out) => RegorusResult {
status: RegorusStatus::RegorusStatusOk,
output: to_c_str(out),
error_message: std::ptr::null_mut(),
},
Err(e) => to_regorus_result(Err(e)),
}
}

/// Gets the parameters defined in each policy added to the engine.
///
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Engine.html#method.get_policy_parameters
#[no_mangle]
#[cfg(feature = "azure_policy")]
pub extern "C" fn regorus_engine_get_policy_parameters(engine: *mut RegorusEngine) -> RegorusResult {
let output = || -> Result<String> { serde_json::to_string_pretty(&to_ref(engine)?.engine.get_policy_parameters()?).map_err(anyhow::Error::msg) }();
match output {
Ok(out) => RegorusResult {
status: RegorusStatus::RegorusStatusOk,
output: to_c_str(out),
error_message: std::ptr::null_mut(),
},
Err(e) => to_regorus_result(Err(e)),
}
}

/// Enable/disable rego v1.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_rego_v0
Expand Down
132 changes: 132 additions & 0 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,31 @@ pub struct Engine {
rego_v1: bool,
}

#[derive(Debug, Clone, Serialize)]
pub struct PolicyPackageNameDefinition {
pub source_file: String,
pub package_name: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct PolicyParameter {
pub name: String,
pub modifiable: bool,
pub required: bool,
}

#[derive(Debug, Clone, Serialize)]
pub struct PolicyModifier {
pub name: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct PolicyParameters {
pub source_file: String,
pub parameters: Vec<PolicyParameter>,
pub modifiers: Vec<PolicyModifier>,
}

/// Create a default engine.
impl Default for Engine {
fn default() -> Self {
Expand Down Expand Up @@ -907,6 +932,113 @@ impl Engine {
serde_json::to_string_pretty(&ast).map_err(anyhow::Error::msg)
}

/// Get the package names of each policy added to the engine.
///
///
/// ```rust
/// # use regorus::*;
/// # use anyhow::{bail, Result};
/// # fn main() -> Result<()> {
/// # let mut engine = Engine::new();
/// engine.add_policy("test.rego".to_string(), "package test\n x := 1".to_string())?;
/// engine.add_policy("test2.rego".to_string(), "package test.multi.segment\n x := 1".to_string())?;
///
/// let package_names = engine.get_policy_package_names()?;
///
/// assert_eq!("test", package_names[0].package_name);
/// assert_eq!("test.multi.segment", package_names[1].package_name);
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "azure_policy")]
#[cfg_attr(docsrs, doc(cfg(feature = "azure_policy")))]
pub fn get_policy_package_names(&self) -> Result<Vec<PolicyPackageNameDefinition>> {
Comment thread
anakrish marked this conversation as resolved.
let mut package_names = vec![];
for m in &self.modules {
let package_name = Interpreter::get_path_string(&m.package.refr, None)?;
package_names.push(PolicyPackageNameDefinition {
source_file: m.package.span.source.file().to_string(),
package_name,
});
}

Ok(package_names)
}

/// Get the parameters defined in each policy.
///
///
/// ```rust
/// # use regorus::*;
/// # use anyhow::{bail, Result};
/// # fn main() -> Result<()> {
/// # let mut engine = Engine::new();
/// engine.add_policy("test.rego".to_string(), "package test default parameters.a = 5 parameters.b = 10\n x := 1".to_string())?;
///
/// let parameters = engine.get_policy_parameters()?;
///
/// assert_eq!("a", parameters[0].parameters[0].name);
/// assert_eq!("b", parameters[0].modifiers[0].name);
///
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "azure_policy")]
#[cfg_attr(docsrs, doc(cfg(feature = "azure_policy")))]
pub fn get_policy_parameters(&self) -> Result<Vec<PolicyParameters>> {
let mut policy_parameter_definitions = vec![];
for m in &self.modules {
Comment thread
anakrish marked this conversation as resolved.
let mut parameters = vec![];
let mut modifiers = vec![];

for rule in &m.policy {
// Extract parameter definitions from the policy rule
// e.g. default parameters.a = 5
if let Rule::Default { refr, .. } = rule.as_ref() {
let path = Parser::get_path_ref_components(refr)?;
let paths: Vec<&str> = path.iter().map(|s| s.text()).collect();

if paths.len() == 2 && paths[0] == "parameters" {
// Todo: Fetch fields other than name from rego metadoc for the parameter
parameters.push(PolicyParameter {
name: paths[1].to_string(),
modifiable: false,
required: false,
})
}
}

// Extract modifiers to the parameters from the policy rule
Comment thread
anakrish marked this conversation as resolved.
// e.g. parameters.a = 5
if let Rule::Spec { head, .. } = rule.as_ref() {
match head {
RuleHead::Compr { refr, .. } => {
let path = Parser::get_path_ref_components(refr)?;
let paths: Vec<&str> = path.iter().map(|s| s.text()).collect();

if paths.len() == 2 && paths[0] == "parameters" {
// Todo: Fetch fields other than name from rego metadoc for the parameter
modifiers.push(PolicyModifier {
name: paths[1].to_string(),
})
}
}
RuleHead::Func { .. } => {}
RuleHead::Set { .. } => {}
}
}
}

policy_parameter_definitions.push(PolicyParameters {
source_file: m.package.span.source.file().to_string(),
parameters,
modifiers,
});
}

Ok(policy_parameter_definitions)
}

fn make_parser<'a>(&self, source: &'a Source) -> Result<Parser<'a>> {
let mut parser = Parser::new(source)?;
if self.rego_v1 {
Expand Down
Loading
Loading