mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat: Complete target system with C# bindings and resource inference (#458)
* feat: Add Schema Registry and Validation Framework This commit introduces a comprehensive schema registry and validation framework, providing schema-based validation of resources and policy effects. - Thread-safe, in-memory registry for schema storage and management - Global registry patterns for effects and resources - Concurrent access with proper error handling - Unicode schema names support - JSON Schema-compliant validation for all primitive types - Advanced constraint validation (patterns, ranges, length limits) - Discriminated union support with anyOf schemas - Detailed error reporting with nested validation paths - Discriminated subobject validation for polymorphic schemas - **Registry Tests**: All registry operations - **Effect Tests**: Policy effect validation - **Resource Tests**: Resource validation - **Validation Tests**: Core validation engine - Thread-safety, error handling, integration scenarios, edge cases - **Dependencies**: dashmap, once_cell, regex - **Thread Safety**: Minimal locking with Rc<Schema> sharing - **Error Types**: TypeMismatch, OutOfRange, PatternMismatch, etc. - Complete schema registry and validation subsystem - Comprehensive test coverage - Foundation for policy validation in Regorus Benchmarks: - Criterion benchmarks for basic types, effects and Azure resources - Performance range: 3.22ns (string) to 34.74µs (Azure VM resource schema validation) - String withs patterns validation: 30.2µs. Need to explore whether regex caching helps bring this down. - Azure policy effects: 188ns-1.4µs Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com> * feat: Complete target system with C# bindings and resource inference - Add comprehensive target system with TargetRegistry and target-aware compilation - Implement resource type inference from policy equality expressions - Create modular C# bindings with separate wrapper classes for each concept - Add thread-safe CompiledPolicy with reference counting for safe disposal - Enhance FFI with detailed error propagation and target functionality - Create TargetExampleApp demonstrating Azure Policy integration - Add CI/CD pipeline testing for all C# applications - Support target definitions with schema validation and resource selectors - Implement PolicyModule struct and target-aware compilation methods - Add comprehensive test coverage for target functionality Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com> --------- Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
3c33d31d08
commit
cc917ea75d
@@ -0,0 +1,168 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
#nullable enable
|
||||
namespace Regorus
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a compiled Regorus policy that can be evaluated efficiently.
|
||||
/// This class wraps a pre-compiled policy that can be evaluated multiple times
|
||||
/// with different inputs without recompilation overhead.
|
||||
///
|
||||
/// This class manages unmanaged resources and should not be copied or cloned.
|
||||
/// Each instance represents a unique native policy object.
|
||||
///
|
||||
/// Thread Safety: This class is thread-safe for all operations. Multiple threads
|
||||
/// can safely call EvalWithInput() concurrently, and Dispose() will safely wait
|
||||
/// for all active evaluations to complete before freeing resources. No external
|
||||
/// synchronization is required.
|
||||
/// </summary>
|
||||
public unsafe sealed class CompiledPolicy : IDisposable
|
||||
{
|
||||
private Internal.RegorusCompiledPolicy* _policy;
|
||||
private int _isDisposed;
|
||||
private int _activeEvaluations;
|
||||
|
||||
internal CompiledPolicy(Internal.RegorusCompiledPolicy* policy)
|
||||
{
|
||||
_policy = policy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the compiled policy with the given input.
|
||||
/// For target policies, evaluates the target's effect rule.
|
||||
/// For regular policies, evaluates the originally compiled rule.
|
||||
/// </summary>
|
||||
/// <param name="inputJson">JSON encoded input data (resource) to validate against the policy</param>
|
||||
/// <returns>The evaluation result as JSON string</returns>
|
||||
/// <exception cref="Exception">Thrown when policy evaluation fails</exception>
|
||||
/// <exception cref="ObjectDisposedException">Thrown when the policy has been disposed</exception>
|
||||
public string? EvalWithInput(string inputJson)
|
||||
{
|
||||
// Increment active evaluations count
|
||||
System.Threading.Interlocked.Increment(ref _activeEvaluations);
|
||||
try
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
var inputBytes = Encoding.UTF8.GetBytes(inputJson + char.MinValue);
|
||||
fixed (byte* inputPtr = inputBytes)
|
||||
{
|
||||
return CheckAndDropResult(Internal.API.regorus_compiled_policy_eval_with_input(_policy, inputPtr));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Decrement active evaluations count
|
||||
System.Threading.Interlocked.Decrement(ref _activeEvaluations);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about the compiled policy including metadata about modules,
|
||||
/// target configuration, and resource types.
|
||||
/// </summary>
|
||||
/// <returns>Policy information containing module IDs, target name, applicable resource types, entry point rule, and parameters</returns>
|
||||
/// <exception cref="Exception">Thrown when getting policy info fails</exception>
|
||||
/// <exception cref="ObjectDisposedException">Thrown when the policy has been disposed</exception>
|
||||
public PolicyInfo GetPolicyInfo()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
var jsonResult = CheckAndDropResult(Internal.API.regorus_compiled_policy_get_policy_info(_policy));
|
||||
|
||||
if (string.IsNullOrEmpty(jsonResult))
|
||||
{
|
||||
throw new Exception("Failed to get policy info: empty response");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
return JsonSerializer.Deserialize<PolicyInfo>(jsonResult!, options)
|
||||
?? throw new Exception("Failed to deserialize policy info");
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
throw new Exception($"Failed to parse policy info JSON: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (System.Threading.Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0)
|
||||
{
|
||||
if (_policy != null)
|
||||
{
|
||||
// Wait for all active evaluations to complete
|
||||
while (System.Threading.Volatile.Read(ref _activeEvaluations) > 0)
|
||||
{
|
||||
System.Threading.Thread.Yield();
|
||||
}
|
||||
|
||||
Internal.API.regorus_compiled_policy_drop(_policy);
|
||||
_policy = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~CompiledPolicy() => Dispose(disposing: false);
|
||||
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
if (_isDisposed != 0)
|
||||
throw new ObjectDisposedException(nameof(CompiledPolicy));
|
||||
}
|
||||
|
||||
private string? StringFromUTF8(IntPtr ptr)
|
||||
{
|
||||
#if NETSTANDARD2_1
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr);
|
||||
#else
|
||||
int len = 0;
|
||||
while (System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0) { ++len; }
|
||||
byte[] buffer = new byte[len];
|
||||
System.Runtime.InteropServices.Marshal.Copy(ptr, buffer, 0, buffer.Length);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
private string? CheckAndDropResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown error occurred");
|
||||
}
|
||||
|
||||
return result.data_type switch
|
||||
{
|
||||
Internal.RegorusDataType.String => StringFromUTF8((IntPtr)result.output),
|
||||
Internal.RegorusDataType.Boolean => result.bool_value.ToString().ToLowerInvariant(),
|
||||
Internal.RegorusDataType.Integer => result.int_value.ToString(),
|
||||
Internal.RegorusDataType.None => null,
|
||||
_ => StringFromUTF8((IntPtr)result.output)
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
#nullable enable
|
||||
namespace Regorus
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a policy module with an ID and content.
|
||||
/// </summary>
|
||||
public struct PolicyModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier for this policy module.
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Rego policy content.
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the PolicyModule struct.
|
||||
/// </summary>
|
||||
/// <param name="id">The unique identifier for this policy module</param>
|
||||
/// <param name="content">The Rego policy content</param>
|
||||
public PolicyModule(string id, string content)
|
||||
{
|
||||
Id = id;
|
||||
Content = content;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides static methods for compiling policies into efficient compiled representations.
|
||||
/// These are convenience methods that create an engine internally and perform compilation.
|
||||
/// </summary>
|
||||
public static unsafe class Compiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Compiles a policy from data and modules with a specific entry point rule.
|
||||
/// This is a convenience function that sets up an Engine internally and calls the appropriate compilation method.
|
||||
/// </summary>
|
||||
/// <param name="dataJson">JSON string containing static data for policy evaluation</param>
|
||||
/// <param name="modules">List of policy modules to compile</param>
|
||||
/// <param name="entryPointRule">The specific rule path to evaluate (e.g., "data.policy.allow")</param>
|
||||
/// <returns>A compiled policy that can be evaluated efficiently</returns>
|
||||
/// <exception cref="Exception">Thrown when compilation fails</exception>
|
||||
public static CompiledPolicy CompilePolicyWithEntrypoint(string dataJson, IEnumerable<PolicyModule> modules, string entryPointRule)
|
||||
{
|
||||
var dataBytes = Encoding.UTF8.GetBytes(dataJson + char.MinValue);
|
||||
var entryPointBytes = Encoding.UTF8.GetBytes(entryPointRule + char.MinValue);
|
||||
var modulesArray = modules.ToArray();
|
||||
|
||||
// Convert C# modules to native structs
|
||||
var nativeModules = new Internal.RegorusPolicyModule[modulesArray.Length];
|
||||
var pinnedHandles = new List<GCHandle>();
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < modulesArray.Length; i++)
|
||||
{
|
||||
var idBytes = Encoding.UTF8.GetBytes(modulesArray[i].Id + char.MinValue);
|
||||
var contentBytes = Encoding.UTF8.GetBytes(modulesArray[i].Content + char.MinValue);
|
||||
|
||||
var idHandle = GCHandle.Alloc(idBytes, GCHandleType.Pinned);
|
||||
var contentHandle = GCHandle.Alloc(contentBytes, GCHandleType.Pinned);
|
||||
pinnedHandles.Add(idHandle);
|
||||
pinnedHandles.Add(contentHandle);
|
||||
|
||||
nativeModules[i] = new Internal.RegorusPolicyModule
|
||||
{
|
||||
id = (byte*)idHandle.AddrOfPinnedObject(),
|
||||
content = (byte*)contentHandle.AddrOfPinnedObject()
|
||||
};
|
||||
}
|
||||
|
||||
fixed (byte* dataPtr = dataBytes)
|
||||
fixed (byte* entryPointPtr = entryPointBytes)
|
||||
fixed (Internal.RegorusPolicyModule* modulesPtr = nativeModules)
|
||||
{
|
||||
var result = Internal.API.regorus_compile_policy_with_entrypoint(
|
||||
dataPtr, modulesPtr, (UIntPtr)modulesArray.Length, entryPointPtr);
|
||||
|
||||
var policy = GetCompiledPolicyResult(result);
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var handle in pinnedHandles)
|
||||
{
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a target-aware policy from data and modules.
|
||||
/// This is a convenience function that sets up an Engine internally and calls target-aware compilation.
|
||||
/// At least one module must contain a `__target__` declaration.
|
||||
/// </summary>
|
||||
/// <param name="dataJson">JSON string containing static data for policy evaluation</param>
|
||||
/// <param name="modules">List of policy modules to compile</param>
|
||||
/// <returns>A compiled policy that can be evaluated efficiently</returns>
|
||||
/// <exception cref="Exception">Thrown when compilation fails</exception>
|
||||
public static CompiledPolicy CompilePolicyForTarget(string dataJson, IEnumerable<PolicyModule> modules)
|
||||
{
|
||||
var dataBytes = Encoding.UTF8.GetBytes(dataJson + char.MinValue);
|
||||
var modulesArray = modules.ToArray();
|
||||
|
||||
// Convert C# modules to native structs
|
||||
var nativeModules = new Internal.RegorusPolicyModule[modulesArray.Length];
|
||||
var pinnedHandles = new List<GCHandle>();
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < modulesArray.Length; i++)
|
||||
{
|
||||
var idBytes = Encoding.UTF8.GetBytes(modulesArray[i].Id + char.MinValue);
|
||||
var contentBytes = Encoding.UTF8.GetBytes(modulesArray[i].Content + char.MinValue);
|
||||
|
||||
var idHandle = GCHandle.Alloc(idBytes, GCHandleType.Pinned);
|
||||
var contentHandle = GCHandle.Alloc(contentBytes, GCHandleType.Pinned);
|
||||
pinnedHandles.Add(idHandle);
|
||||
pinnedHandles.Add(contentHandle);
|
||||
|
||||
nativeModules[i] = new Internal.RegorusPolicyModule
|
||||
{
|
||||
id = (byte*)idHandle.AddrOfPinnedObject(),
|
||||
content = (byte*)contentHandle.AddrOfPinnedObject()
|
||||
};
|
||||
}
|
||||
|
||||
fixed (byte* dataPtr = dataBytes)
|
||||
fixed (Internal.RegorusPolicyModule* modulesPtr = nativeModules)
|
||||
{
|
||||
var result = Internal.API.regorus_compile_policy_for_target(
|
||||
dataPtr, modulesPtr, (UIntPtr)modulesArray.Length);
|
||||
|
||||
var policy = GetCompiledPolicyResult(result);
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var handle in pinnedHandles)
|
||||
{
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string? StringFromUTF8(IntPtr ptr)
|
||||
{
|
||||
#if NETSTANDARD2_1
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr);
|
||||
#else
|
||||
int len = 0;
|
||||
while (System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0) { ++len; }
|
||||
byte[] buffer = new byte[len];
|
||||
System.Runtime.InteropServices.Marshal.Copy(ptr, buffer, 0, buffer.Length);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static CompiledPolicy GetCompiledPolicyResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown compilation error occurred");
|
||||
}
|
||||
|
||||
if (result.data_type != Internal.RegorusDataType.Pointer || result.pointer_value == null)
|
||||
{
|
||||
throw new Exception("Expected compiled policy pointer but got different data type");
|
||||
}
|
||||
|
||||
return new CompiledPolicy((Internal.RegorusCompiledPolicy*)result.pointer_value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +243,7 @@ namespace Regorus
|
||||
|
||||
string? CheckAndDropResult(Regorus.Internal.RegorusResult result)
|
||||
{
|
||||
if (result.status != Regorus.Internal.RegorusStatus.RegorusStatusOk)
|
||||
if (result.status != Regorus.Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
var ex = new Exception(message);
|
||||
@@ -0,0 +1,546 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
|
||||
namespace Regorus.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Native FFI method declarations for Regorus.
|
||||
/// This file contains all P/Invoke declarations for the Regorus native library.
|
||||
/// </summary>
|
||||
internal static unsafe partial class API
|
||||
{
|
||||
private const string LibraryName = "regorus_ffi";
|
||||
|
||||
#region Common Methods
|
||||
|
||||
/// <summary>
|
||||
/// Drop a RegorusResult.
|
||||
/// output and error_message strings are not valid after drop.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_result_drop", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern void regorus_result_drop(RegorusResult result);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Engine Methods
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Engine.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusEngine* regorus_engine_new();
|
||||
|
||||
/// <summary>
|
||||
/// Clone a RegorusEngine.
|
||||
/// To avoid having to parse same policy again, the engine can be cloned
|
||||
/// after policies and data have been added.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusEngine* regorus_engine_clone(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Drop a RegorusEngine.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_drop", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern void regorus_engine_drop(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Add a policy.
|
||||
/// The policy is parsed into AST.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_policy
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_add_policy", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_policy(RegorusEngine* engine, byte* path, byte* rego);
|
||||
|
||||
/// <summary>
|
||||
/// Add a policy from file.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_add_policy_from_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_policy_from_file(RegorusEngine* engine, byte* path);
|
||||
|
||||
/// <summary>
|
||||
/// Add policy data.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_data
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_add_data_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_data_json(RegorusEngine* engine, byte* data);
|
||||
|
||||
/// <summary>
|
||||
/// Get list of loaded Rego packages as JSON.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_packages
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_get_packages", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_packages(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Get list of policies as JSON.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_policies
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_get_policies", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_policies(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Add data from JSON file.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_add_data_from_json_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_data_from_json_file(RegorusEngine* engine, byte* path);
|
||||
|
||||
/// <summary>
|
||||
/// Clear policy data.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_data
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_clear_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_clear_data(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Set input.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_input
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_set_input_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_input_json(RegorusEngine* engine, byte* input);
|
||||
|
||||
/// <summary>
|
||||
/// Set input from JSON file.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_set_input_from_json_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_input_from_json_file(RegorusEngine* engine, byte* path);
|
||||
|
||||
/// <summary>
|
||||
/// Evaluate query.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_query
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_eval_query", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_eval_query(RegorusEngine* engine, byte* query);
|
||||
|
||||
/// <summary>
|
||||
/// Evaluate specified rule.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_rule
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_eval_rule", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_eval_rule(RegorusEngine* engine, byte* rule);
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable coverage.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_enable_coverage
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_set_enable_coverage", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_enable_coverage(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool enable);
|
||||
|
||||
/// <summary>
|
||||
/// Get coverage report.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_coverage_report
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_get_coverage_report", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_coverage_report(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable strict builtin errors.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_strict_builtin_errors
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_set_strict_builtin_errors", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_strict_builtin_errors(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool strict);
|
||||
|
||||
/// <summary>
|
||||
/// Get pretty printed coverage report.
|
||||
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Report.html#method.to_string_pretty
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_get_coverage_report_pretty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_coverage_report_pretty(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Clear coverage data.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_coverage_data
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_clear_coverage_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_clear_coverage_data(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Whether to gather output of print statements.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_gather_prints
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_set_gather_prints", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_gather_prints(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool enable);
|
||||
|
||||
/// <summary>
|
||||
/// Take all the gathered print statements.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.take_prints
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_take_prints", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_take_prints(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Get AST of policies.
|
||||
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Engine.html#method.get_ast_as_json
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, 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 defined in each policy added to the engine.
|
||||
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Engine.html#method.get_policy_package_names
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, 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(LibraryName, 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.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_rego_v0
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_set_rego_v0", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_rego_v0(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool enable);
|
||||
|
||||
/// <summary>
|
||||
/// Compile a target-aware policy from the current engine state.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.compile_for_target
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_compile_for_target", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_compile_for_target(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Compile a policy with a specific entry point rule.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.compile_with_entrypoint
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_engine_compile_with_entrypoint", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_compile_with_entrypoint(RegorusEngine* engine, byte* rule);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Compilation Methods
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a policy from data and modules with a specific entry point rule.
|
||||
/// This is a convenience function that wraps regorus::compile_policy_with_entrypoint.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_compile_policy_with_entrypoint", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_compile_policy_with_entrypoint(byte* data_json, RegorusPolicyModule* modules, UIntPtr modules_len, byte* entry_point_rule);
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a target-aware policy from data and modules.
|
||||
/// This is a convenience function that wraps regorus::compile_policy_for_target.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_compile_policy_for_target", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_compile_policy_for_target(byte* data_json, RegorusPolicyModule* modules, UIntPtr modules_len);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Compiled Policy Methods
|
||||
|
||||
/// <summary>
|
||||
/// Drop a RegorusCompiledPolicy.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_compiled_policy_drop", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern void regorus_compiled_policy_drop(RegorusCompiledPolicy* compiled_policy);
|
||||
|
||||
/// <summary>
|
||||
/// Evaluate the compiled policy with the given input.
|
||||
/// For target policies, evaluates the target's effect rule.
|
||||
/// For regular policies, evaluates the originally compiled rule.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_compiled_policy_eval_with_input", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_compiled_policy_eval_with_input(RegorusCompiledPolicy* compiled_policy, byte* input);
|
||||
|
||||
/// <summary>
|
||||
/// Get information about the compiled policy including metadata about modules,
|
||||
/// target configuration, and resource types.
|
||||
/// Returns a JSON-encoded PolicyInfo struct containing comprehensive
|
||||
/// information about the compiled policy such as module IDs, target name,
|
||||
/// applicable resource types, entry point rule, and parameters.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_compiled_policy_get_policy_info", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_compiled_policy_get_policy_info(RegorusCompiledPolicy* compiled_policy);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Target Registry Methods
|
||||
|
||||
/// <summary>
|
||||
/// Register a target from JSON definition.
|
||||
/// The target JSON should follow the target schema format.
|
||||
/// Once registered, the target can be referenced in Rego policies using __target__ rules.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_register_target_from_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_register_target_from_json(byte* target_json);
|
||||
|
||||
/// <summary>
|
||||
/// Check if a target is registered.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_target_registry_contains", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_target_registry_contains(byte* name);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all registered target names as JSON array.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_target_registry_list_names", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_target_registry_list_names();
|
||||
|
||||
/// <summary>
|
||||
/// Remove a target from the registry by name.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_target_registry_remove", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_target_registry_remove(byte* name);
|
||||
|
||||
/// <summary>
|
||||
/// Clear all targets from the registry.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_target_registry_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_target_registry_clear();
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of registered targets.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_target_registry_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_target_registry_len();
|
||||
|
||||
/// <summary>
|
||||
/// Check if the target registry is empty.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_target_registry_is_empty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_target_registry_is_empty();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resource Schema Registry Methods
|
||||
|
||||
/// <summary>
|
||||
/// Register a resource schema from JSON with a given name.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_resource_schema_register", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_resource_schema_register(byte* name, byte* schema_json);
|
||||
|
||||
/// <summary>
|
||||
/// Check if a resource schema with the given name exists.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_resource_schema_contains", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_resource_schema_contains(byte* name);
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of registered resource schemas.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_resource_schema_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_resource_schema_len();
|
||||
|
||||
/// <summary>
|
||||
/// Check if the resource schema registry is empty.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_resource_schema_is_empty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_resource_schema_is_empty();
|
||||
|
||||
/// <summary>
|
||||
/// List all registered resource schema names as a JSON array.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_resource_schema_list_names", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_resource_schema_list_names();
|
||||
|
||||
/// <summary>
|
||||
/// Remove a resource schema by name.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_resource_schema_remove", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_resource_schema_remove(byte* name);
|
||||
|
||||
/// <summary>
|
||||
/// Clear all resource schemas from the registry.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_resource_schema_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_resource_schema_clear();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Effect Schema Registry Methods
|
||||
|
||||
/// <summary>
|
||||
/// Register an effect schema from JSON with a given name.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_effect_schema_register", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_effect_schema_register(byte* name, byte* schema_json);
|
||||
|
||||
/// <summary>
|
||||
/// Check if an effect schema with the given name exists.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_effect_schema_contains", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_effect_schema_contains(byte* name);
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of registered effect schemas.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_effect_schema_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_effect_schema_len();
|
||||
|
||||
/// <summary>
|
||||
/// Check if the effect schema registry is empty.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_effect_schema_is_empty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_effect_schema_is_empty();
|
||||
|
||||
/// <summary>
|
||||
/// List all registered effect schema names as a JSON array.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_effect_schema_list_names", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_effect_schema_list_names();
|
||||
|
||||
/// <summary>
|
||||
/// Remove an effect schema by name.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_effect_schema_remove", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_effect_schema_remove(byte* name);
|
||||
|
||||
/// <summary>
|
||||
/// Clear all effect schemas from the registry.
|
||||
/// </summary>
|
||||
[DllImport(LibraryName, EntryPoint = "regorus_effect_schema_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_effect_schema_clear();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Native Structures
|
||||
|
||||
/// <summary>
|
||||
/// Type of data contained in RegorusResult.
|
||||
/// </summary>
|
||||
internal enum RegorusDataType : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// No data / void.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// String data (output field is valid).
|
||||
/// </summary>
|
||||
String,
|
||||
/// <summary>
|
||||
/// Boolean data (bool_value field is valid).
|
||||
/// </summary>
|
||||
Boolean,
|
||||
/// <summary>
|
||||
/// Integer data (int_value field is valid).
|
||||
/// </summary>
|
||||
Integer,
|
||||
/// <summary>
|
||||
/// Pointer data (pointer_value field is valid).
|
||||
/// </summary>
|
||||
Pointer,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status of a call on RegorusEngine.
|
||||
/// </summary>
|
||||
internal enum RegorusStatus : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// The operation was successful.
|
||||
/// </summary>
|
||||
Ok,
|
||||
/// <summary>
|
||||
/// The operation was unsuccessful.
|
||||
/// </summary>
|
||||
Error,
|
||||
/// <summary>
|
||||
/// Invalid data format provided.
|
||||
/// </summary>
|
||||
InvalidDataFormat,
|
||||
/// <summary>
|
||||
/// Invalid entrypoint rule specified.
|
||||
/// </summary>
|
||||
InvalidEntrypoint,
|
||||
/// <summary>
|
||||
/// Compilation failed.
|
||||
/// </summary>
|
||||
CompilationFailed,
|
||||
/// <summary>
|
||||
/// Invalid argument provided.
|
||||
/// </summary>
|
||||
InvalidArgument,
|
||||
/// <summary>
|
||||
/// Invalid module ID.
|
||||
/// </summary>
|
||||
InvalidModuleId,
|
||||
/// <summary>
|
||||
/// Invalid policy content.
|
||||
/// </summary>
|
||||
InvalidPolicy,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result of a call on RegorusEngine.
|
||||
/// Must be freed using regorus_result_drop.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe partial struct RegorusResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Status.
|
||||
/// </summary>
|
||||
public RegorusStatus status;
|
||||
/// <summary>
|
||||
/// Type of data contained in this result.
|
||||
/// </summary>
|
||||
public RegorusDataType data_type;
|
||||
/// <summary>
|
||||
/// String output produced by the call.
|
||||
/// Valid when data_type is String. Owned by Rust.
|
||||
/// </summary>
|
||||
public byte* output;
|
||||
/// <summary>
|
||||
/// Boolean value.
|
||||
/// Valid when data_type is Boolean.
|
||||
/// </summary>
|
||||
public bool bool_value;
|
||||
/// <summary>
|
||||
/// Integer value.
|
||||
/// Valid when data_type is Integer.
|
||||
/// </summary>
|
||||
public long int_value;
|
||||
/// <summary>
|
||||
/// Pointer value.
|
||||
/// Valid when data_type is Pointer.
|
||||
/// </summary>
|
||||
public void* pointer_value;
|
||||
/// <summary>
|
||||
/// Errors produced by the call.
|
||||
/// Owned by Rust.
|
||||
/// </summary>
|
||||
public byte* error_message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for regorus::Engine.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe partial struct RegorusEngine
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for regorus::CompiledPolicy.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe partial struct RegorusCompiledPolicy
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FFI wrapper for PolicyModule struct.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe partial struct RegorusPolicyModule
|
||||
{
|
||||
public byte* id;
|
||||
public byte* content;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
#nullable enable
|
||||
namespace Regorus
|
||||
{
|
||||
/// <summary>
|
||||
/// Information about a compiled policy, including metadata about modules,
|
||||
/// target configuration, and resource types that the policy can evaluate.
|
||||
/// </summary>
|
||||
public class PolicyInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// List of module identifiers that were compiled into this policy.
|
||||
/// Each module ID represents a unique policy module that contributes
|
||||
/// rules, functions, or data to the compiled policy.
|
||||
/// </summary>
|
||||
[JsonPropertyName("module_ids")]
|
||||
public List<string> ModuleIds { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Name of the target configuration used during compilation, if any.
|
||||
/// This indicates which target schema and validation rules were applied.
|
||||
/// </summary>
|
||||
[JsonPropertyName("target_name")]
|
||||
public string? TargetName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of resource types that this policy can evaluate.
|
||||
/// For target-aware policies, this contains the inferred or configured
|
||||
/// resource types. For general policies, this may be empty.
|
||||
/// </summary>
|
||||
[JsonPropertyName("applicable_resource_types")]
|
||||
public List<string> ApplicableResourceTypes { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// The primary rule or entrypoint that this policy evaluates.
|
||||
/// This is the rule path that will be executed when the policy runs.
|
||||
/// </summary>
|
||||
[JsonPropertyName("entrypoint_rule")]
|
||||
public string EntrypointRule { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The effect rule name for target-aware policies, if applicable.
|
||||
/// This is the specific effect rule (e.g., "effect", "allow", "deny")
|
||||
/// that determines the policy decision for target evaluation.
|
||||
/// </summary>
|
||||
[JsonPropertyName("effect_rule")]
|
||||
public string? EffectRule { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parameters that can be configured for this policy.
|
||||
/// Contains parameter names and their expected types or default values.
|
||||
/// Used for parameterized policies that accept configuration at evaluation time.
|
||||
/// Each element represents parameters from a different module.
|
||||
/// </summary>
|
||||
[JsonPropertyName("parameters")]
|
||||
public List<PolicyParameters> Parameters { get; set; } = new List<PolicyParameters>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parameters that can be configured for a policy.
|
||||
/// </summary>
|
||||
public class PolicyParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Source file where the parameters are defined.
|
||||
/// </summary>
|
||||
[JsonPropertyName("source_file")]
|
||||
public string SourceFile { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// List of parameter definitions.
|
||||
/// </summary>
|
||||
[JsonPropertyName("parameters")]
|
||||
public List<PolicyParameter> Parameters { get; set; } = new List<PolicyParameter>();
|
||||
|
||||
/// <summary>
|
||||
/// List of parameter modifiers.
|
||||
/// </summary>
|
||||
[JsonPropertyName("modifiers")]
|
||||
public List<PolicyParameterModifier> Modifiers { get; set; } = new List<PolicyParameterModifier>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A single parameter definition.
|
||||
/// </summary>
|
||||
public class PolicyParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the parameter.
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Type of the parameter.
|
||||
/// </summary>
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Default value of the parameter, if any.
|
||||
/// </summary>
|
||||
[JsonPropertyName("default")]
|
||||
public object? Default { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Description of the parameter.
|
||||
/// </summary>
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allowed values for the parameter, if constrained.
|
||||
/// </summary>
|
||||
[JsonPropertyName("allowed_values")]
|
||||
public List<object>? AllowedValues { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A parameter modifier that affects parameter behavior.
|
||||
/// </summary>
|
||||
public class PolicyParameterModifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the modifier.
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Value of the modifier.
|
||||
/// </summary>
|
||||
[JsonPropertyName("value")]
|
||||
public object? Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,10 @@
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
$(RegorusFFIArtifactsDir) is the location where regorus shared libraries have been
|
||||
built for various platforms and copied to. RegorusFFIArtifactsDir is passed in
|
||||
@@ -20,8 +24,10 @@
|
||||
|
||||
For each target triple, `Pack` expects the regorus ffi shared library
|
||||
to be found in $(RegorusFFIArtifactsDir)/<target-triple>/release.
|
||||
|
||||
If $(IgnoreMissingArtifacts) is not set, ensure that the binaries for officially supported platforms exists.
|
||||
-->
|
||||
<Target Name="ChecksRegorusFFIArtifactsDir" BeforeTargets="Pack">
|
||||
<Target Name="ChecksRegorusFFIArtifactsDir" BeforeTargets="Pack" Condition="'$(IgnoreMissingArtifacts)' == ''">
|
||||
<Error Text="RegorusFFIArtifactsDir must be supplied." Condition="$(RegorusFFIArtifactsDir) == ''" />
|
||||
|
||||
<!-- Ensure that the binaries for officially supported platforms exists. -->
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace Regorus.Internal
|
||||
{
|
||||
internal static unsafe partial class API
|
||||
{
|
||||
const string __DllName = "regorus_ffi";
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Drop a `RegorusResult`.
|
||||
///
|
||||
/// `output` and `error_message` strings are not valid after drop.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_result_drop", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern void regorus_result_drop(RegorusResult r);
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Engine
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusEngine* regorus_engine_new();
|
||||
|
||||
/// <summary>
|
||||
/// Clone a [`RegorusEngine`]
|
||||
///
|
||||
/// To avoid having to parse same policy again, the engine can be cloned
|
||||
/// after policies and data have been added.
|
||||
///
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusEngine* regorus_engine_clone(RegorusEngine* engine);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_drop", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern void regorus_engine_drop(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Add a policy
|
||||
///
|
||||
/// The policy is parsed into AST.
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_policy
|
||||
///
|
||||
/// * `path`: A filename to be associated with the policy.
|
||||
/// * `rego`: Rego policy.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_add_policy", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_policy(RegorusEngine* engine, byte* path, byte* rego);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_add_policy_from_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_policy_from_file(RegorusEngine* engine, byte* path);
|
||||
|
||||
/// <summary>
|
||||
/// Add policy data.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_data
|
||||
/// * `data`: JSON encoded value to be used as policy data.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_add_data_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_data_json(RegorusEngine* engine, byte* data);
|
||||
|
||||
/// <summary>
|
||||
/// Get list of loaded Rego packages as JSON.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_packages
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_get_packages", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_packages(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Get list of policies as JSON.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_policies
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_get_policies", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_policies(RegorusEngine* engine);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_add_data_from_json_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_add_data_from_json_file(RegorusEngine* engine, byte* path);
|
||||
|
||||
/// <summary>
|
||||
/// Clear policy data.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_data
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_clear_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_clear_data(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_set_input_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_input_json(RegorusEngine* engine, byte* input);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_set_input_from_json_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_input_from_json_file(RegorusEngine* engine, byte* path);
|
||||
|
||||
/// <summary>
|
||||
/// Evaluate query.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_query
|
||||
/// * `query`: Rego expression to be evaluate.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_eval_query", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_eval_query(RegorusEngine* engine, byte* query);
|
||||
|
||||
/// <summary>
|
||||
/// Evaluate specified rule.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_rule
|
||||
/// * `rule`: Path to the rule.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_eval_rule", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_eval_rule(RegorusEngine* engine, byte* rule);
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable coverage.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_enable_coverage
|
||||
/// * `enable`: Whether to enable or disable coverage.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_set_enable_coverage", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_enable_coverage(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool enable);
|
||||
|
||||
/// <summary>
|
||||
/// Get coverage report.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_coverage_report
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_get_coverage_report", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_coverage_report(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable strict builtin errors.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_strict_builtin_errors
|
||||
/// * `strict`: Whether to raise errors or return undefined on certain scenarios.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_set_strict_builtin_errors", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_strict_builtin_errors(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool strict);
|
||||
|
||||
/// <summary>
|
||||
/// Get pretty printed coverage report.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Report.html#method.to_string_pretty
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_get_coverage_report_pretty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_get_coverage_report_pretty(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Clear coverage data.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_coverage_data
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_clear_coverage_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_clear_coverage_data(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Whether to gather output of print statements.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_gather_prints
|
||||
/// * `enable`: Whether to enable or disable gathering print statements.
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_set_gather_prints", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_gather_prints(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool enable);
|
||||
|
||||
/// <summary>
|
||||
/// Take all the gathered print statements.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.take_prints
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_take_prints", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_take_prints(RegorusEngine* engine);
|
||||
|
||||
/// <summary>
|
||||
/// Get AST of policies.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Engine.html#method.get_ast_as_json
|
||||
/// </summary>
|
||||
[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.
|
||||
///
|
||||
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_rego_v0
|
||||
/// </summary>
|
||||
[DllImport(__DllName, EntryPoint = "regorus_engine_set_rego_v0", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
internal static extern RegorusResult regorus_engine_set_rego_v0(RegorusEngine* engine, [MarshalAs(UnmanagedType.U1)] bool enable);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe partial struct RegorusResult
|
||||
{
|
||||
public RegorusStatus status;
|
||||
public byte* output;
|
||||
public byte* error_message;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe partial struct RegorusEngine
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
internal enum RegorusStatus : uint
|
||||
{
|
||||
RegorusStatusOk,
|
||||
RegorusStatusError,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
#nullable enable
|
||||
namespace Regorus
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides static methods for managing the global resource schema registry.
|
||||
/// Resource schemas define the structure and validation rules for Azure Policy resources.
|
||||
/// </summary>
|
||||
public static unsafe class SchemaRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Register a resource schema from JSON with a given name.
|
||||
/// </summary>
|
||||
/// <param name="name">Name to register the schema under</param>
|
||||
/// <param name="schemaJson">JSON string representing the schema</param>
|
||||
/// <exception cref="Exception">Thrown when schema registration fails</exception>
|
||||
public static void RegisterResource(string name, string schemaJson)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
var schemaBytes = Encoding.UTF8.GetBytes(schemaJson + char.MinValue);
|
||||
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
fixed (byte* schemaPtr = schemaBytes)
|
||||
{
|
||||
CheckAndDropResult(Internal.API.regorus_resource_schema_register(namePtr, schemaPtr));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a resource schema with the given name exists.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the schema to check</param>
|
||||
/// <returns>True if the schema exists, false otherwise</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool ContainsResource(string name)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
{
|
||||
var result = Internal.API.regorus_resource_schema_contains(namePtr);
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of registered resource schemas.
|
||||
/// </summary>
|
||||
/// <returns>The number of registered resource schemas</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static long ResourceCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Internal.API.regorus_resource_schema_len();
|
||||
return GetIntResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the resource schema registry is empty.
|
||||
/// </summary>
|
||||
/// <returns>True if the registry is empty, false otherwise</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool IsResourceRegistryEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Internal.API.regorus_resource_schema_is_empty();
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all registered resource schema names.
|
||||
/// </summary>
|
||||
/// <returns>JSON array of schema names</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static string ListResourceNames()
|
||||
{
|
||||
return CheckAndDropResult(Internal.API.regorus_resource_schema_list_names()) ?? "[]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a resource schema by name.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the schema to remove</param>
|
||||
/// <returns>True if the schema was removed, false if it wasn't found</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool RemoveResource(string name)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
{
|
||||
var result = Internal.API.regorus_resource_schema_remove(namePtr);
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all resource schemas from the registry.
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static void ClearResources()
|
||||
{
|
||||
CheckAndDropResult(Internal.API.regorus_resource_schema_clear());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an effect schema from JSON with a given name.
|
||||
/// </summary>
|
||||
/// <param name="name">Name to register the schema under</param>
|
||||
/// <param name="schemaJson">JSON string representing the schema</param>
|
||||
/// <exception cref="Exception">Thrown when schema registration fails</exception>
|
||||
public static void RegisterEffect(string name, string schemaJson)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
var schemaBytes = Encoding.UTF8.GetBytes(schemaJson + char.MinValue);
|
||||
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
fixed (byte* schemaPtr = schemaBytes)
|
||||
{
|
||||
CheckAndDropResult(Internal.API.regorus_effect_schema_register(namePtr, schemaPtr));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if an effect schema with the given name exists.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the schema to check</param>
|
||||
/// <returns>True if the schema exists, false otherwise</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool ContainsEffect(string name)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
{
|
||||
var result = Internal.API.regorus_effect_schema_contains(namePtr);
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of registered effect schemas.
|
||||
/// </summary>
|
||||
/// <returns>The number of registered effect schemas</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static long EffectCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Internal.API.regorus_effect_schema_len();
|
||||
return GetIntResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the effect schema registry is empty.
|
||||
/// </summary>
|
||||
/// <returns>True if the registry is empty, false otherwise</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool IsEffectRegistryEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Internal.API.regorus_effect_schema_is_empty();
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all registered effect schema names.
|
||||
/// </summary>
|
||||
/// <returns>JSON array of schema names</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static string ListEffectNames()
|
||||
{
|
||||
return CheckAndDropResult(Internal.API.regorus_effect_schema_list_names()) ?? "[]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove an effect schema by name.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the schema to remove</param>
|
||||
/// <returns>True if the schema was removed, false if it wasn't found</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool RemoveEffect(string name)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
{
|
||||
var result = Internal.API.regorus_effect_schema_remove(namePtr);
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all effect schemas from the registry.
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static void ClearEffects()
|
||||
{
|
||||
CheckAndDropResult(Internal.API.regorus_effect_schema_clear());
|
||||
}
|
||||
|
||||
private static string? StringFromUTF8(IntPtr ptr)
|
||||
{
|
||||
#if NETSTANDARD2_1
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr);
|
||||
#else
|
||||
int len = 0;
|
||||
while (System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0) { ++len; }
|
||||
byte[] buffer = new byte[len];
|
||||
System.Runtime.InteropServices.Marshal.Copy(ptr, buffer, 0, buffer.Length);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static string? CheckAndDropResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown error occurred");
|
||||
}
|
||||
|
||||
return result.data_type switch
|
||||
{
|
||||
Internal.RegorusDataType.String => StringFromUTF8((IntPtr)result.output),
|
||||
Internal.RegorusDataType.Boolean => result.bool_value.ToString().ToLowerInvariant(),
|
||||
Internal.RegorusDataType.Integer => result.int_value.ToString(),
|
||||
Internal.RegorusDataType.None => null,
|
||||
_ => StringFromUTF8((IntPtr)result.output)
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool GetBoolResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown error occurred");
|
||||
}
|
||||
|
||||
return result.data_type == Internal.RegorusDataType.Boolean ? result.bool_value : false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static long GetIntResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown error occurred");
|
||||
}
|
||||
|
||||
return result.data_type == Internal.RegorusDataType.Integer ? result.int_value : 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
#nullable enable
|
||||
namespace Regorus
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides static methods for managing the global target registry.
|
||||
/// Targets define resource types and their associated schemas for Azure Policy evaluation.
|
||||
/// </summary>
|
||||
public static unsafe class TargetRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Register a target from JSON definition.
|
||||
/// The target JSON should follow the target schema format.
|
||||
/// Once registered, the target can be referenced in Rego policies using `__target__` rules.
|
||||
/// </summary>
|
||||
/// <param name="targetJson">JSON encoded target definition</param>
|
||||
/// <exception cref="Exception">Thrown when target registration fails</exception>
|
||||
public static void RegisterFromJson(string targetJson)
|
||||
{
|
||||
var targetBytes = Encoding.UTF8.GetBytes(targetJson + char.MinValue);
|
||||
fixed (byte* targetPtr = targetBytes)
|
||||
{
|
||||
CheckAndDropResult(Internal.API.regorus_register_target_from_json(targetPtr));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a target is registered.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the target to check</param>
|
||||
/// <returns>True if the target is registered, false otherwise</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool Contains(string name)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
{
|
||||
var result = Internal.API.regorus_target_registry_contains(namePtr);
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all registered target names.
|
||||
/// </summary>
|
||||
/// <returns>JSON array of target names</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static string ListNames()
|
||||
{
|
||||
return CheckAndDropResult(Internal.API.regorus_target_registry_list_names()) ?? "[]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a target from the registry by name.
|
||||
/// </summary>
|
||||
/// <param name="name">The target name to remove</param>
|
||||
/// <returns>True if the target was removed, false if it wasn't found</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool Remove(string name)
|
||||
{
|
||||
var nameBytes = Encoding.UTF8.GetBytes(name + char.MinValue);
|
||||
fixed (byte* namePtr = nameBytes)
|
||||
{
|
||||
var result = Internal.API.regorus_target_registry_remove(namePtr);
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all targets from the registry.
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static void Clear()
|
||||
{
|
||||
CheckAndDropResult(Internal.API.regorus_target_registry_clear());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of registered targets.
|
||||
/// </summary>
|
||||
/// <returns>The number of registered targets</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static long Count
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Internal.API.regorus_target_registry_len();
|
||||
return GetIntResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the target registry is empty.
|
||||
/// </summary>
|
||||
/// <returns>True if the registry is empty, false otherwise</returns>
|
||||
/// <exception cref="Exception">Thrown when the operation fails</exception>
|
||||
public static bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Internal.API.regorus_target_registry_is_empty();
|
||||
return GetBoolResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static string? StringFromUTF8(IntPtr ptr)
|
||||
{
|
||||
#if NETSTANDARD2_1
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr);
|
||||
#else
|
||||
int len = 0;
|
||||
while (System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0) { ++len; }
|
||||
byte[] buffer = new byte[len];
|
||||
System.Runtime.InteropServices.Marshal.Copy(ptr, buffer, 0, buffer.Length);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static string? CheckAndDropResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown error occurred");
|
||||
}
|
||||
|
||||
return result.data_type switch
|
||||
{
|
||||
Internal.RegorusDataType.String => StringFromUTF8((IntPtr)result.output),
|
||||
Internal.RegorusDataType.Boolean => result.bool_value.ToString().ToLowerInvariant(),
|
||||
Internal.RegorusDataType.Integer => result.int_value.ToString(),
|
||||
Internal.RegorusDataType.None => null,
|
||||
_ => StringFromUTF8((IntPtr)result.output)
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool GetBoolResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown error occurred");
|
||||
}
|
||||
|
||||
return result.data_type == Internal.RegorusDataType.Boolean ? result.bool_value : false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static long GetIntResult(Internal.RegorusResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.status != Internal.RegorusStatus.Ok)
|
||||
{
|
||||
var message = StringFromUTF8((IntPtr)result.error_message);
|
||||
throw new Exception(message ?? "Unknown error occurred");
|
||||
}
|
||||
|
||||
return result.data_type == Internal.RegorusDataType.Integer ? result.int_value : 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Internal.API.regorus_result_drop(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user