// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; using System.Collections.Generic; using System.Linq; using Regorus.Internal; #nullable enable namespace Regorus { /// /// Represents a policy module with an ID and content. /// public readonly struct PolicyModule { /// /// Gets the unique identifier for this policy module. /// public string Id { get; } /// /// Gets the Rego policy content. /// public string Content { get; } /// /// Initializes a new instance of the PolicyModule struct. /// /// The unique identifier for this policy module /// The Rego policy content public PolicyModule(string id, string content) { Id = id; Content = content; } } /// /// Provides static methods for compiling policies into efficient compiled representations. /// These are convenience methods that create an engine internally and perform compilation. /// public static unsafe class Compiler { /// /// 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. /// /// JSON string containing static data for policy evaluation /// List of policy modules to compile /// The specific rule path to evaluate (e.g., "data.policy.allow") /// A compiled policy that can be evaluated efficiently /// Thrown when compilation fails public static CompiledPolicy CompilePolicyWithEntrypoint(string dataJson, IEnumerable modules, string entryPointRule) { if (modules is null) { throw new ArgumentNullException(nameof(modules)); } return CompilePolicyWithEntrypoint(dataJson, modules.ToArray(), entryPointRule); } /// /// Compiles a policy from data and modules with a specific entry point rule. /// public static CompiledPolicy CompilePolicyWithEntrypoint(string dataJson, IReadOnlyList modules, string entryPointRule) { if (modules is null) { throw new ArgumentNullException(nameof(modules)); } using var pinnedModules = Internal.ModuleMarshalling.PinPolicyModules(modules); return Utf8Marshaller.WithUtf8(dataJson, dataPtr => Utf8Marshaller.WithUtf8(entryPointRule, entryPointPtr => { unsafe { fixed (Internal.RegorusPolicyModule* modulesPtr = pinnedModules.Buffer) { var result = Internal.API.regorus_compile_policy_with_entrypoint( (byte*)dataPtr, modulesPtr, (UIntPtr)pinnedModules.Length, (byte*)entryPointPtr); return GetCompiledPolicyResult(result); } } })); } /// /// 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. /// /// JSON string containing static data for policy evaluation /// List of policy modules to compile /// A compiled policy that can be evaluated efficiently /// Thrown when compilation fails public static CompiledPolicy CompilePolicyForTarget(string dataJson, IEnumerable modules) { if (modules is null) { throw new ArgumentNullException(nameof(modules)); } return CompilePolicyForTarget(dataJson, modules.ToArray()); } /// /// Compiles a target-aware policy from data and modules. /// public static CompiledPolicy CompilePolicyForTarget(string dataJson, IReadOnlyList modules) { if (modules is null) { throw new ArgumentNullException(nameof(modules)); } using var pinnedModules = Internal.ModuleMarshalling.PinPolicyModules(modules); return Utf8Marshaller.WithUtf8(dataJson, dataPtr => { unsafe { fixed (Internal.RegorusPolicyModule* modulesPtr = pinnedModules.Buffer) { var result = Internal.API.regorus_compile_policy_for_target( (byte*)dataPtr, modulesPtr, (UIntPtr)pinnedModules.Length); return GetCompiledPolicyResult(result); } } }); } private static CompiledPolicy GetCompiledPolicyResult(Internal.RegorusResult result) { try { if (result.status != Internal.RegorusStatus.Ok) { var message = Utf8Marshaller.FromUtf8(result.error_message); throw result.status.CreateException(message); } if (result.data_type != Internal.RegorusDataType.Pointer || result.pointer_value == null) { throw new Exception("Expected compiled policy pointer but got different data type"); } var handle = RegorusCompiledPolicyHandle.FromPointer((IntPtr)result.pointer_value); return new CompiledPolicy(handle); } finally { Internal.API.regorus_result_drop(result); } } } }