From 5456ba86c1128ed35477ccc565786cc63609d04f Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 15 Feb 2024 03:51:10 +0000 Subject: [PATCH 01/21] add extension_list example --- .../extension_list/extension-data-empty.json | 2 ++ .../extension_list/extension-data-empty2.json | 4 +++ examples/extension_list/extension-data.json | 15 +++++++++++ .../extension-input-newVersion.json | 20 ++++++++++++++ examples/extension_list/extension-input.json | 20 ++++++++++++++ examples/extension_list/extension_policy.rego | 27 +++++++++++++++++++ 6 files changed, 88 insertions(+) create mode 100644 examples/extension_list/extension-data-empty.json create mode 100644 examples/extension_list/extension-data-empty2.json create mode 100644 examples/extension_list/extension-data.json create mode 100644 examples/extension_list/extension-input-newVersion.json create mode 100644 examples/extension_list/extension-input.json create mode 100644 examples/extension_list/extension_policy.rego diff --git a/examples/extension_list/extension-data-empty.json b/examples/extension_list/extension-data-empty.json new file mode 100644 index 00000000..2c63c085 --- /dev/null +++ b/examples/extension_list/extension-data-empty.json @@ -0,0 +1,2 @@ +{ +} diff --git a/examples/extension_list/extension-data-empty2.json b/examples/extension_list/extension-data-empty2.json new file mode 100644 index 00000000..63c1a5d4 --- /dev/null +++ b/examples/extension_list/extension-data-empty2.json @@ -0,0 +1,4 @@ +{ + "allowed": [ + ] +} diff --git a/examples/extension_list/extension-data.json b/examples/extension_list/extension-data.json new file mode 100644 index 00000000..fd20bba9 --- /dev/null +++ b/examples/extension_list/extension-data.json @@ -0,0 +1,15 @@ +{ + "allowed": { + "ext1": { + "version": "1.0", + "upgradable": false + }, + "ext2": { + "signature": "xyz245", + "upgradable": true + }, + "App3": { + "type": "app" + } + } +} diff --git a/examples/extension_list/extension-input-newVersion.json b/examples/extension_list/extension-input-newVersion.json new file mode 100644 index 00000000..6b6c3ebd --- /dev/null +++ b/examples/extension_list/extension-input-newVersion.json @@ -0,0 +1,20 @@ +{ + "incoming": { + "ext1": { + "urls": ["url1", "url2"], + "state": "enabled", + "settings":["setting1", "setting2"], + "version": "1.1" + }, + "ext2": { + "location": "url2", + "state": "disabled", + "version": "2.0" + }, + "ext3": { + "location": "url3", + "state": "enabled", + "version": "1.0" + } + } +} diff --git a/examples/extension_list/extension-input.json b/examples/extension_list/extension-input.json new file mode 100644 index 00000000..5331c71e --- /dev/null +++ b/examples/extension_list/extension-input.json @@ -0,0 +1,20 @@ +{ + "incoming": { + "ext1": { + "urls": ["url1", "url2"], + "state": "enabled", + "settings":["setting1", "setting2"], + "version": "1.0" + }, + "ext2": { + "location": "url2", + "state": "disabled", + "version": "2.0" + }, + "ext3": { + "location": "url3", + "state": "enabled", + "version": "1.0" + } + } +} diff --git a/examples/extension_list/extension_policy.rego b/examples/extension_list/extension_policy.rego new file mode 100644 index 00000000..2ec3881f --- /dev/null +++ b/examples/extension_list/extension_policy.rego @@ -0,0 +1,27 @@ +package extension_policy + +import rego.v1 + +allowed_extensions[name] := extension if { + some name, input_extension in input.incoming + extension_is_allowed(input_extension, data.allowed[name]) + extension := object.union(input_extension, data.allowed[name]) +} + +extension_is_allowed(input_data, allowed_data) if { + allowed_data + check_optional_properties(input_data, allowed_data) +} + +check_optional_properties(input_data, allowed) if { + not allowed.version +} else if { + allowed.version + input_data.version == allowed.version +} + +denied_extensions[name] := extension if { + some name, input_extension in input.incoming + not extension_is_allowed(input_extension, data.allowed[name]) + extension := input_extension +} From 71edf9e5bccf579044351566745133b21505eb5b Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 15 Feb 2024 03:55:22 +0000 Subject: [PATCH 02/21] fix the json format for empty list --- examples/extension_list/extension-data-empty2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/extension_list/extension-data-empty2.json b/examples/extension_list/extension-data-empty2.json index 63c1a5d4..2bdbbded 100644 --- a/examples/extension_list/extension-data-empty2.json +++ b/examples/extension_list/extension-data-empty2.json @@ -1,4 +1,4 @@ { - "allowed": [ - ] + "allowed": { + } } From e81727ddd2b1101b6658dc043cc22c04bcbbc9fc Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 15 Feb 2024 21:41:28 +0000 Subject: [PATCH 03/21] enable csharp build --- bindings/csharp/regorus-test.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/csharp/regorus-test.csproj b/bindings/csharp/regorus-test.csproj index ddf818d6..0267fedf 100644 --- a/bindings/csharp/regorus-test.csproj +++ b/bindings/csharp/regorus-test.csproj @@ -1,4 +1,4 @@ - + From 798db9c3afb5f4aa8b54fda28303e7db1983be89 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Tue, 20 Feb 2024 16:15:01 +0000 Subject: [PATCH 04/21] support 'all' options in data --- .../extension_list/extension-data-All.json | 5 ++++ .../extension_list/extension-data-all.json | 5 ++++ examples/extension_list/extension_policy.rego | 25 +++++++++++++++---- 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 examples/extension_list/extension-data-All.json create mode 100644 examples/extension_list/extension-data-all.json diff --git a/examples/extension_list/extension-data-All.json b/examples/extension_list/extension-data-All.json new file mode 100644 index 00000000..48202d9e --- /dev/null +++ b/examples/extension_list/extension-data-All.json @@ -0,0 +1,5 @@ +{ + "allowed": { + "All":{} + } +} diff --git a/examples/extension_list/extension-data-all.json b/examples/extension_list/extension-data-all.json new file mode 100644 index 00000000..b90be2a4 --- /dev/null +++ b/examples/extension_list/extension-data-all.json @@ -0,0 +1,5 @@ +{ + "allowed": { + "all":{} + } +} diff --git a/examples/extension_list/extension_policy.rego b/examples/extension_list/extension_policy.rego index 2ec3881f..00669941 100644 --- a/examples/extension_list/extension_policy.rego +++ b/examples/extension_list/extension_policy.rego @@ -2,15 +2,21 @@ package extension_policy import rego.v1 +allowed_extensions[name] := extension if { + check_all_data_allowed(data.allowed) # Checks if 'all' is a key in data.allowed + some name, input_extension in input.incoming # Assign any incoming extension name to 'name' + extension := input_extension # Assign the extension itself +} + allowed_extensions[name] := extension if { some name, input_extension in input.incoming - extension_is_allowed(input_extension, data.allowed[name]) + extension_is_allowed(input_extension, data.allowed, name) extension := object.union(input_extension, data.allowed[name]) } -extension_is_allowed(input_data, allowed_data) if { - allowed_data - check_optional_properties(input_data, allowed_data) +extension_is_allowed(input_data, allowed_data, name) if { + allowed_data[name] + check_optional_properties(input_data, allowed_data[name]) } check_optional_properties(input_data, allowed) if { @@ -20,8 +26,17 @@ check_optional_properties(input_data, allowed) if { input_data.version == allowed.version } +check_all_data_allowed(data_allowed) if { + data_allowed.all +} else if { + data_allowed.ALL +} else if { + data_allowed.All +} + denied_extensions[name] := extension if { + not check_all_data_allowed(data.allowed) some name, input_extension in input.incoming - not extension_is_allowed(input_extension, data.allowed[name]) + not extension_is_allowed(input_extension, data.allowed, name) extension := input_extension } From 8fa6ca7852b0028a77f1fd37ade71d2834b5ee8a Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Wed, 21 Feb 2024 21:10:19 +0000 Subject: [PATCH 05/21] change name to support windows name convention --- .../{extension-data-All.json => extension-data-all2.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/extension_list/{extension-data-All.json => extension-data-all2.json} (100%) diff --git a/examples/extension_list/extension-data-All.json b/examples/extension_list/extension-data-all2.json similarity index 100% rename from examples/extension_list/extension-data-All.json rename to examples/extension_list/extension-data-all2.json From ccbe4836f9bd63c4d8c6d9153ab742c808e77bf0 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 22 Feb 2024 10:32:57 -0500 Subject: [PATCH 06/21] add C# .net4.6.2 example --- bindings/csharp/net4.6/Program.cs | 60 ++++++++ bindings/csharp/net4.6/Regorus.cs | 170 +++++++++++++++++++++ bindings/csharp/net4.6/regorus-test.csproj | 26 ++++ 3 files changed, 256 insertions(+) create mode 100644 bindings/csharp/net4.6/Program.cs create mode 100644 bindings/csharp/net4.6/Regorus.cs create mode 100644 bindings/csharp/net4.6/regorus-test.csproj diff --git a/bindings/csharp/net4.6/Program.cs b/bindings/csharp/net4.6/Program.cs new file mode 100644 index 00000000..3a83e59f --- /dev/null +++ b/bindings/csharp/net4.6/Program.cs @@ -0,0 +1,60 @@ +using System; +using System.Text; +using System.Text.Json; +using System.Diagnostics; + +namespace regoregorus_test +{ + class Program + { + static void Main(string[] args) + { + long nanosecPerTick = (1000L * 1000L * 1000L) / Stopwatch.Frequency; + var w = new Stopwatch(); + + + // Force load of modules. + { + var _e = new Regorus.Engine(); + var _j = System.Text.Json.JsonDocument.Parse("{}"); + } + + w.Restart(); + + var engine = new Regorus.Engine(); + + w.Stop(); + var newEngineTicks = w.ElapsedTicks; + + + w.Restart(); + + // Load policies and data. + engine.AddPolicyFromFile("../../../examples/extension_list/extension_policy.rego"); + engine.AddDataFromJsonFile("../../../examples/extension_list/extension-data.json"); + + + w.Stop(); + var loadPoliciesTicks = w.ElapsedTicks; + + + w.Restart(); + + // Set input and eval query. + engine.SetInputFromJsonFile("../../../examples/extension_list/extension-input.json"); + var results = engine.EvalQuery("data.extension_policy.allowed_extensions"); + var resultsDoc = System.Text.Json.JsonDocument.Parse(results); + + w.Stop(); + var evalTicks = w.ElapsedTicks; + + Console.WriteLine("{0}", results); + + + Console.WriteLine("Engine creation took {0} msecs", (newEngineTicks * nanosecPerTick) / (1000.0 * 1000.0)); + Console.WriteLine("Load policies and data took {0} msecs", (loadPoliciesTicks * nanosecPerTick) / (1000.0 * 1000.0)); + Console.WriteLine("EvalQuery took {0} msecs", (evalTicks * nanosecPerTick) / (1000.0 * 1000.0)); + } + } +} + diff --git a/bindings/csharp/net4.6/Regorus.cs b/bindings/csharp/net4.6/Regorus.cs new file mode 100644 index 00000000..eabd0bbc --- /dev/null +++ b/bindings/csharp/net4.6/Regorus.cs @@ -0,0 +1,170 @@ +using System; +using System.Text; + +namespace Regorus +{ + public class Exception : System.Exception + { + public Exception(string message) : base(message) {} + } + + public class Engine : ICloneable + { + unsafe private RegorusFFI.RegorusEngine* E; + public Engine() + { + unsafe + { + E = RegorusFFI.API.regorus_engine_new(); + } + } + + public object Clone() + { + var clone = (Engine)this.MemberwiseClone(); + unsafe + { + clone.E = RegorusFFI.API.regorus_engine_clone(E); + } + return clone; + + } + + public void AddPolicy(string path, string rego) + { + var pathBytes = Encoding.UTF8.GetBytes(path); + var regoBytes = Encoding.UTF8.GetBytes(rego); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + fixed(byte* regoPtr = regoBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy(E, pathPtr, regoPtr)); + } + } + } + } + + public void AddPolicyFromFile(string path) + { + var pathBytes = Encoding.UTF8.GetBytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy_from_file(E, pathPtr)); + } + } + } + + public void AddDataJson(string data) + { + var dataBytes = Encoding.UTF8.GetBytes(data); + + unsafe + { + fixed (byte* dataPtr = dataBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_json(E, dataPtr)); + + } + } + } + + public void AddDataFromJsonFile(string path) + { + var pathBytes = Encoding.UTF8.GetBytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_from_json_file(E, pathPtr)); + + } + } + } + + public void SetInputJson(string input) + { + var inputBytes = Encoding.UTF8.GetBytes(input); + + unsafe + { + fixed (byte* inputPtr = inputBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_json(E, inputPtr)); + + } + } + } + + public void SetInputFromJsonFile(string path) + { + var pathBytes = Encoding.UTF8.GetBytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_from_json_file(E, pathPtr)); + + } + } + } + + public string EvalQuery(string query) + { + var queryBytes = Encoding.UTF8.GetBytes(query); + + var resultJson = ""; + unsafe + { + fixed (byte* queryPtr = queryBytes) + { + var result = RegorusFFI.API.regorus_engine_eval_query(E, queryPtr); + if (result.status == RegorusFFI.RegorusStatus.RegorusStatusOk) { + if (result.output != null) { + resultJson = System.Runtime.InteropServices.Marshal.PtrToStringAnsi((IntPtr)result.output); + } + RegorusFFI.API.regorus_result_drop(result); + } else { + CheckAndDropResult(result); + } + + } + } + if (resultJson != null) { + return resultJson; + } else { + return ""; + } + } + + ~Engine() + { + unsafe + { + RegorusFFI.API.regorus_engine_drop(E); + } + } + + + void CheckAndDropResult(RegorusFFI.RegorusResult result) + { + if (result.status != RegorusFFI.RegorusStatus.RegorusStatusOk) { + unsafe { + var message = System.Runtime.InteropServices.Marshal.PtrToStringAnsi((IntPtr)result.error_message); + var ex = new Exception(message); + RegorusFFI.API.regorus_result_drop(result); + throw ex; + } + } + RegorusFFI.API.regorus_result_drop(result); + } + + } +} diff --git a/bindings/csharp/net4.6/regorus-test.csproj b/bindings/csharp/net4.6/regorus-test.csproj new file mode 100644 index 00000000..90f3a2bf --- /dev/null +++ b/bindings/csharp/net4.6/regorus-test.csproj @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + Exe + net4.6.2 + regorus_test + regoregorus_test.Program + enable + true + + + + + From 663fe33a122ce7adb47dd5d03ce8f2977df69459 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Wed, 24 Apr 2024 19:43:00 +0000 Subject: [PATCH 07/21] new policy and data files according to design review --- .../agent-extension-data-all.json | 19 +++ .../agent-extension-data-allow-only.json | 19 +++ .../extension_list/agent-extension-input.json | 20 +++ .../agent_extension_policy.rego | 122 ++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 examples/extension_list/agent-extension-data-all.json create mode 100644 examples/extension_list/agent-extension-data-allow-only.json create mode 100644 examples/extension_list/agent-extension-input.json create mode 100644 examples/extension_list/agent_extension_policy.rego diff --git a/examples/extension_list/agent-extension-data-all.json b/examples/extension_list/agent-extension-data-all.json new file mode 100644 index 00000000..ecee611a --- /dev/null +++ b/examples/extension_list/agent-extension-data-all.json @@ -0,0 +1,19 @@ +{ + "azureGuestAgentPolicy": { + "signingRules": { + "extensionSigned": true + }, + "allowListOnly": false + }, + "azureGuestExtensionsPolicy": { + "test2": { + "runtimeRules": {} + }, + "test3": { + "signingRules": { + "extensionSigned": false + }, + "runtimeRules": {} + } + } +} diff --git a/examples/extension_list/agent-extension-data-allow-only.json b/examples/extension_list/agent-extension-data-allow-only.json new file mode 100644 index 00000000..312e467f --- /dev/null +++ b/examples/extension_list/agent-extension-data-allow-only.json @@ -0,0 +1,19 @@ +{ + "azureGuestAgentPolicy": { + "signingRules": { + "extensionSigned": true + }, + "allowListOnly": true + }, + "azureGuestExtensionsPolicy": { + "test3": { + "runtimeRules": {} + }, + "test2": { + "signingRules": { + "extensionSigned": false + }, + "runtimeRules": {} + } + } +} diff --git a/examples/extension_list/agent-extension-input.json b/examples/extension_list/agent-extension-input.json new file mode 100644 index 00000000..9aa8d4eb --- /dev/null +++ b/examples/extension_list/agent-extension-input.json @@ -0,0 +1,20 @@ +{ + "extensions": { + "test2": { + "signingInfo": { + "extensionSigned": true + } + }, + "test3": { + "signingInfo": { + "extensionSigned": false + } + }, + "test1": { + "signingInfo": { + "extensionSigned": false + } + }, + "test4": {} + } +} diff --git a/examples/extension_list/agent_extension_policy.rego b/examples/extension_list/agent_extension_policy.rego new file mode 100644 index 00000000..28dcfa7e --- /dev/null +++ b/examples/extension_list/agent_extension_policy.rego @@ -0,0 +1,122 @@ +package agent_extension_policy + +import rego.v1 + +policy_version := "0.1.0" + +default default_global_rules := { + "allowListOnly": false, + "signingRules": { + "extensionSigned": false, + "signingDetails": {}, + }, + "updateAllowed": true, + "uninstallAllowed": true, +} + +default global_rules := { + "allowListOnly": false, + "signingRules": { + "extensionSigned": false, + "signingDetails": {}, + }, + "updateAllowed": true, + "uninstallAllowed": true, +} + +global_rules := object.union(default_global_rules, data.azureGuestAgentPolicy) if { + data.azureGuestAgentPolicy +} + +default any_extension_allowed := true + +any_extension_allowed := false if { + global_rules.allowListOnly +} + +default default_signing_info := {"signingInfo": {}} + +# Download rule 1: if the extension is in the list and download rule satisfied: download allowed +extensions_to_download[name] := extension if { + some name, input_extension in input.extensions + data.azureGuestExtensionsPolicy[name] + download_rule_validated(input_extension, data.azureGuestExtensionsPolicy[name]) + extension := object.union(input_extension, {"downloadAllowed": true}) +} + +# Download rule 2: if the extension is in the list and download rule not satisfied: download denied +extensions_to_download[name] := extension if { + some name, input_extension in input.extensions + data.azureGuestExtensionsPolicy[name] + not download_rule_validated(input_extension, data.azureGuestExtensionsPolicy[name]) + extension := object.union(input_extension, {"downloadAllowed": false}) +} + +# Download rule 3: if the extension is not in the list: depending on allowListOnly on or off +extensions_to_download[name] := extension if { + some name, input_extension in input.extensions + not data.azureGuestExtensionsPolicy[name] + extension := object.union(input_extension, {"downloadAllowed": any_extension_allowed}) +} + +# Validate rule 1: if individual signing rule exists, signing rule validated according to the rules +extensions_validated[name] := extension if { + some name, input_extension in input.extensions + data.azureGuestExtensionsPolicy[name] + + extension_global_rules := object.union(global_rules, data.azureGuestExtensionsPolicy[name]) + extension_signing_info := object.union(extension_global_rules, default_signing_info) + output := object.union(input_extension, extension_signing_info) + signing_validated(output.signingInfo, output.signingRules) + extension := object.union(output, {"signingValidated": true}) +} + +# Validate rule 2: if indivual signing rule exists, signing rule not validated according to the rules +extensions_validated[name] := extension if { + some name, input_extension in input.extensions + data.azureGuestExtensionsPolicy[name] + + extension_global_rules := object.union(global_rules, data.azureGuestExtensionsPolicy[name]) + extension_signing_info := object.union(extension_global_rules, default_signing_info) + output := object.union(input_extension, extension_signing_info) + not signing_validated(output.signingInfo, output.signingRules) + extension := object.union(output, {"signingValidated": false}) +} + +# Validate rule 3: if individual signing rule doesn't exist, signing rule validated according to global signing rule +extensions_validated[name] := extension if { + some name, input_extension in input.extensions + not data.azureGuestExtensionsPolicy[name] + extension_global_rules := object.union(input_extension, global_rules) + output := object.union(extension_global_rules, default_signing_info) + signing_validated(output.signingInfo, output.signingRules) + extension := object.union(output, {"signingValidated": true}) +} + +# Validate rule 4: if individual signing rule doesn't exist, signing rule not validated according to the global rules +extensions_validated[name] := extension if { + some name, input_extension in input.extensions + not data.azureGuestExtensionsPolicy[name] + extension_global_rules := object.union(input_extension, global_rules) + output := object.union(extension_global_rules, default_signing_info) + not signing_validated(output.signingInfo, output.signingRules) + extension := object.union(output, {"signingValidated": false}) +} + +# Currently if download rules doesn't exist, allow the extension because its name is in the list. +# In the future additional rules can be checked with downloadRules present. +download_rule_validated(_, rules) if { + not rules.downloadRules +} + +# Signing is validated if input comes with extension signed, or the input of signing information is matching the +# rules in data. +signing_validated(signingInfo, signingRules) if { + signingInfo + signingRules + signingInfo.extensionSigned +} else if { + signingInfo + signingRules + signingInfo.extensionSigned == signingRules.extensionSigned +} From ae19e2412c4f23178f90deafce3852e93e2bc380 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Tue, 30 Apr 2024 15:26:33 +0000 Subject: [PATCH 08/21] add default data file --- examples/extension_list/agent-extension-default-data.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 examples/extension_list/agent-extension-default-data.json diff --git a/examples/extension_list/agent-extension-default-data.json b/examples/extension_list/agent-extension-default-data.json new file mode 100644 index 00000000..55f745b0 --- /dev/null +++ b/examples/extension_list/agent-extension-default-data.json @@ -0,0 +1,8 @@ +{ + "azureGuestAgentPolicy": { + "signingRules": { + "extensionSigned": false + }, + "allowListOnly": false + } +} From a50f04c1a1460a89035c798c1ee2e9958bfc7267 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Tue, 30 Apr 2024 12:56:06 -0400 Subject: [PATCH 09/21] sync with the agent code --- bindings/csharp/net4.6/Program.cs | 25 ++++++---- bindings/csharp/net4.6/Regorus.cs | 77 ++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 25 deletions(-) diff --git a/bindings/csharp/net4.6/Program.cs b/bindings/csharp/net4.6/Program.cs index 3a83e59f..b64c3a6e 100644 --- a/bindings/csharp/net4.6/Program.cs +++ b/bindings/csharp/net4.6/Program.cs @@ -2,6 +2,7 @@ using System.Text; using System.Text.Json; using System.Diagnostics; +using Microsoft.WindowsAzure.Regorus.IaaS; namespace regoregorus_test { @@ -15,13 +16,13 @@ static void Main(string[] args) // Force load of modules. { - var _e = new Regorus.Engine(); + var _e = new PolicyEngine(); var _j = System.Text.Json.JsonDocument.Parse("{}"); } w.Restart(); - var engine = new Regorus.Engine(); + var engine = new PolicyEngine(); w.Stop(); var newEngineTicks = w.ElapsedTicks; @@ -30,8 +31,8 @@ static void Main(string[] args) w.Restart(); // Load policies and data. - engine.AddPolicyFromFile("../../../examples/extension_list/extension_policy.rego"); - engine.AddDataFromJsonFile("../../../examples/extension_list/extension-data.json"); + engine.AddPolicyFromFile("../../../examples/extension_list/agent_extension_policy.rego"); + engine.AddDataFromJsonFile("../../../examples/extension_list/agent-extension-data-allow-only.json"); w.Stop(); @@ -41,19 +42,25 @@ static void Main(string[] args) w.Restart(); // Set input and eval query. - engine.SetInputFromJsonFile("../../../examples/extension_list/extension-input.json"); - var results = engine.EvalQuery("data.extension_policy.allowed_extensions"); - var resultsDoc = System.Text.Json.JsonDocument.Parse(results); + engine.SetInputFromJsonFile("../../../examples/extension_list/agent-extension-input.json"); + var results = engine.EvalQuery("data.agent_extension_policy.extensions_to_download"); + Console.WriteLine("Download query test: \n {0}", results); + + results = engine.EvalQuery("data.agent_extension_policy.extensions_validated"); + + Console.WriteLine("Signing validation test: \n {0}", results); + + engine.Dispose(); w.Stop(); var evalTicks = w.ElapsedTicks; - Console.WriteLine("{0}", results); + //Console.WriteLine("{0}", results); Console.WriteLine("Engine creation took {0} msecs", (newEngineTicks * nanosecPerTick) / (1000.0 * 1000.0)); Console.WriteLine("Load policies and data took {0} msecs", (loadPoliciesTicks * nanosecPerTick) / (1000.0 * 1000.0)); - Console.WriteLine("EvalQuery took {0} msecs", (evalTicks * nanosecPerTick) / (1000.0 * 1000.0)); + Console.WriteLine("EvalQuery and print results took {0} msecs", (evalTicks * nanosecPerTick) / (1000.0 * 1000.0)); } } } diff --git a/bindings/csharp/net4.6/Regorus.cs b/bindings/csharp/net4.6/Regorus.cs index eabd0bbc..0299680c 100644 --- a/bindings/csharp/net4.6/Regorus.cs +++ b/bindings/csharp/net4.6/Regorus.cs @@ -1,27 +1,61 @@ +//----------------------------------------------------------------------- +// +// Copyright (c)2012 Microsoft. All rights reserved. +// +// +// Contains code for the Regorus Policy Engine base class. +// +//----------------------------------------------------------------------- + + using System; using System.Text; +using System.IO; -namespace Regorus +namespace Microsoft.WindowsAzure.Regorus.IaaS { - public class Exception : System.Exception - { - public Exception(string message) : base(message) {} - } - - public class Engine : ICloneable - { + //public class Exception : System.Exception + //{ + //public Exception(string message) : base(message) {} + //} + public class PolicyEngine : ICloneable, IDisposable + { unsafe private RegorusFFI.RegorusEngine* E; - public Engine() + + public PolicyEngine() { - unsafe + unsafe { E = RegorusFFI.API.regorus_engine_new(); } } + private bool disposed = false; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); // Prevent the destructor from being called + } + + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + unsafe + { + RegorusFFI.API.regorus_engine_drop(E); + } + } + disposed = true; + } + } + public object Clone() { - var clone = (Engine)this.MemberwiseClone(); + var clone = (PolicyEngine)this.MemberwiseClone(); unsafe { clone.E = RegorusFFI.API.regorus_engine_clone(E); @@ -60,6 +94,20 @@ public void AddPolicyFromFile(string path) } } + public void AddPolicyFromPath(string path) + { + if (!Directory.Exists(path)) + { + return; + } + + string[] regoFiles = Directory.GetFiles(path, "*.rego", SearchOption.AllDirectories); + foreach (string file in regoFiles) + { + AddPolicyFromFile(file); + } + } + public void AddDataJson(string data) { var dataBytes = Encoding.UTF8.GetBytes(data); @@ -144,12 +192,9 @@ public string EvalQuery(string query) } } - ~Engine() + ~PolicyEngine() { - unsafe - { - RegorusFFI.API.regorus_engine_drop(E); - } + Dispose(false); } From 9bab2ebf7a29b32df198ef796f2262e8a2900975 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Tue, 30 Apr 2024 13:07:43 -0400 Subject: [PATCH 10/21] remove comment line --- bindings/csharp/net4.6/Program.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/bindings/csharp/net4.6/Program.cs b/bindings/csharp/net4.6/Program.cs index b64c3a6e..4d858f7b 100644 --- a/bindings/csharp/net4.6/Program.cs +++ b/bindings/csharp/net4.6/Program.cs @@ -55,9 +55,6 @@ static void Main(string[] args) w.Stop(); var evalTicks = w.ElapsedTicks; - //Console.WriteLine("{0}", results); - - Console.WriteLine("Engine creation took {0} msecs", (newEngineTicks * nanosecPerTick) / (1000.0 * 1000.0)); Console.WriteLine("Load policies and data took {0} msecs", (loadPoliciesTicks * nanosecPerTick) / (1000.0 * 1000.0)); Console.WriteLine("EvalQuery and print results took {0} msecs", (evalTicks * nanosecPerTick) / (1000.0 * 1000.0)); From 75e18a86fd1d7272fa00fa485602417f5354bd0b Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 2 May 2024 16:23:10 -0400 Subject: [PATCH 11/21] address review comments --- bindings/csharp/net4.6/Program.cs | 2 +- bindings/csharp/net4.6/Regorus.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/csharp/net4.6/Program.cs b/bindings/csharp/net4.6/Program.cs index 4d858f7b..e87df10c 100644 --- a/bindings/csharp/net4.6/Program.cs +++ b/bindings/csharp/net4.6/Program.cs @@ -43,7 +43,7 @@ static void Main(string[] args) // Set input and eval query. engine.SetInputFromJsonFile("../../../examples/extension_list/agent-extension-input.json"); - var results = engine.EvalQuery("data.agent_extension_policy.extensions_to_download"); + var results = engine.EvalQuery("data.agent_extension_policy.extensions_to_download=x"); Console.WriteLine("Download query test: \n {0}", results); results = engine.EvalQuery("data.agent_extension_policy.extensions_validated"); diff --git a/bindings/csharp/net4.6/Regorus.cs b/bindings/csharp/net4.6/Regorus.cs index 0299680c..61397260 100644 --- a/bindings/csharp/net4.6/Regorus.cs +++ b/bindings/csharp/net4.6/Regorus.cs @@ -40,15 +40,15 @@ public void Dispose() protected virtual void Dispose(bool disposing) { - if (!disposed) + if (!disposed && disposing) { - if (disposing) + unsafe { - unsafe - { - RegorusFFI.API.regorus_engine_drop(E); - } + RegorusFFI.API.regorus_engine_drop(E); } + } + if (disposing) + { disposed = true; } } From c6dcc0b4a9c741c00ccd15bd3934bfd8480d6e7f Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Fri, 3 May 2024 15:04:15 -0400 Subject: [PATCH 12/21] simplify the dispose() code --- bindings/csharp/net4.6/Regorus.cs | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/bindings/csharp/net4.6/Regorus.cs b/bindings/csharp/net4.6/Regorus.cs index 61397260..db9188b0 100644 --- a/bindings/csharp/net4.6/Regorus.cs +++ b/bindings/csharp/net4.6/Regorus.cs @@ -11,13 +11,11 @@ using System; using System.Text; using System.IO; +using System.Threading; namespace Microsoft.WindowsAzure.Regorus.IaaS { - //public class Exception : System.Exception - //{ - //public Exception(string message) : base(message) {} - //} + public class PolicyEngine : ICloneable, IDisposable { unsafe private RegorusFFI.RegorusEngine* E; @@ -30,27 +28,20 @@ public PolicyEngine() } } - private bool disposed = false; public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); // Prevent the destructor from being called - } - - protected virtual void Dispose(bool disposing) - { - if (!disposed && disposing) + unsafe { - unsafe + if (E != null) { RegorusFFI.API.regorus_engine_drop(E); + // to avoid Dispose() being called multiple times by mistake. + E = null; } + } - if (disposing) - { - disposed = true; - } + } public object Clone() @@ -192,12 +183,6 @@ public string EvalQuery(string query) } } - ~PolicyEngine() - { - Dispose(false); - } - - void CheckAndDropResult(RegorusFFI.RegorusResult result) { if (result.status != RegorusFFI.RegorusStatus.RegorusStatusOk) { From ab0cb7a2488653d9fcfb8e0f7e197869f0860376 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Fri, 3 May 2024 16:21:53 -0400 Subject: [PATCH 13/21] updated comments about thread-safe --- bindings/csharp/net4.6/Regorus.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bindings/csharp/net4.6/Regorus.cs b/bindings/csharp/net4.6/Regorus.cs index db9188b0..7d268568 100644 --- a/bindings/csharp/net4.6/Regorus.cs +++ b/bindings/csharp/net4.6/Regorus.cs @@ -3,7 +3,10 @@ // Copyright (c)2012 Microsoft. All rights reserved. // // -// Contains code for the Regorus Policy Engine base class. +// Contains code for the Regorus Policy Engine base class for C# and +// .NET4.6 bindings. Currently this base class is not thread-safe. Make +// sure we use it in a signle-threaded environment or add additional +// protection when using it. // //----------------------------------------------------------------------- From f98eda0dde0406425c44b7817c7960538a813db1 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Tue, 7 May 2024 16:58:42 -0400 Subject: [PATCH 14/21] create a nuget spec --- bindings/csharp/net4.6/README | 3 +++ .../net4.6/RegorusCsharp-Lib-x86.nuspec | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 bindings/csharp/net4.6/README create mode 100644 bindings/csharp/net4.6/RegorusCsharp-Lib-x86.nuspec diff --git a/bindings/csharp/net4.6/README b/bindings/csharp/net4.6/README new file mode 100644 index 00000000..52f82de8 --- /dev/null +++ b/bindings/csharp/net4.6/README @@ -0,0 +1,3 @@ +The Regorus C# binding library can be built via command "dotnet build". We can use the Regorus C# binding library built from this +directory to create a Nuget. This Nuget will contain the Regorus C# binding library with base class wrapper and definitions that +work for .NET4.6 and above. Note the Nuget can only be created after the binding library has been built. \ No newline at end of file diff --git a/bindings/csharp/net4.6/RegorusCsharp-Lib-x86.nuspec b/bindings/csharp/net4.6/RegorusCsharp-Lib-x86.nuspec new file mode 100644 index 00000000..2238dbee --- /dev/null +++ b/bindings/csharp/net4.6/RegorusCsharp-Lib-x86.nuspec @@ -0,0 +1,22 @@ + + + + RegorusCsharp-Lib-x86 + 0.0.1 + RegorusCsharp-Lib-x86 + yangjie@microsoft.com + yangjie@microsoft.com + https://www.microsoft.com + false + Regorus C# library for x86 + Initial version for Regorus C# library + Copyright (C) Microsoft Corp + + + + + + + + + \ No newline at end of file From f6fed08b751ec0748d00038c70b06e5672edcbb7 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Tue, 7 May 2024 19:32:02 -0400 Subject: [PATCH 15/21] correct the nuget name --- bindings/csharp/net4.6/README | 3 ++- ...usCsharp-Lib-x86.nuspec => RegorusCsharp-Lib-x64.nuspec} | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) rename bindings/csharp/net4.6/{RegorusCsharp-Lib-x86.nuspec => RegorusCsharp-Lib-x64.nuspec} (84%) diff --git a/bindings/csharp/net4.6/README b/bindings/csharp/net4.6/README index 52f82de8..b48dc9cf 100644 --- a/bindings/csharp/net4.6/README +++ b/bindings/csharp/net4.6/README @@ -1,3 +1,4 @@ The Regorus C# binding library can be built via command "dotnet build". We can use the Regorus C# binding library built from this directory to create a Nuget. This Nuget will contain the Regorus C# binding library with base class wrapper and definitions that -work for .NET4.6 and above. Note the Nuget can only be created after the binding library has been built. \ No newline at end of file +work for .NET4.6 and above. Note the Nuget can only be created after the binding library has been built. +RegorusCsharp-Lib-x64.nuspec is built for x64 architecture. \ No newline at end of file diff --git a/bindings/csharp/net4.6/RegorusCsharp-Lib-x86.nuspec b/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec similarity index 84% rename from bindings/csharp/net4.6/RegorusCsharp-Lib-x86.nuspec rename to bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec index 2238dbee..5af0e9f8 100644 --- a/bindings/csharp/net4.6/RegorusCsharp-Lib-x86.nuspec +++ b/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec @@ -1,14 +1,14 @@ - RegorusCsharp-Lib-x86 + RegorusCsharp-Lib-x64 0.0.1 - RegorusCsharp-Lib-x86 + RegorusCsharp-Lib-x64 yangjie@microsoft.com yangjie@microsoft.com https://www.microsoft.com false - Regorus C# library for x86 + Regorus C# library for x64 Initial version for Regorus C# library Copyright (C) Microsoft Corp From 7d342e75083013ba979917a056d394fd39e223e5 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Wed, 8 May 2024 15:22:32 -0400 Subject: [PATCH 16/21] add policy version to default data --- examples/extension_list/agent-extension-default-data.json | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/extension_list/agent-extension-default-data.json b/examples/extension_list/agent-extension-default-data.json index 55f745b0..e8c4ea8f 100644 --- a/examples/extension_list/agent-extension-default-data.json +++ b/examples/extension_list/agent-extension-default-data.json @@ -1,5 +1,6 @@ { "azureGuestAgentPolicy": { + "policyVersion": "0.1.0", "signingRules": { "extensionSigned": false }, From f638d45768bdfb19c93163c82dbf9c8d6f68b39e Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 9 May 2024 21:32:41 -0400 Subject: [PATCH 17/21] rename policy engine and bump nuspec version --- bindings/csharp/net4.6/Program.cs | 4 ++-- bindings/csharp/net4.6/Regorus.cs | 6 +++--- bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bindings/csharp/net4.6/Program.cs b/bindings/csharp/net4.6/Program.cs index e87df10c..5f0b1e6c 100644 --- a/bindings/csharp/net4.6/Program.cs +++ b/bindings/csharp/net4.6/Program.cs @@ -16,13 +16,13 @@ static void Main(string[] args) // Force load of modules. { - var _e = new PolicyEngine(); + var _e = new RegorusPolicyEngine(); var _j = System.Text.Json.JsonDocument.Parse("{}"); } w.Restart(); - var engine = new PolicyEngine(); + var engine = new RegorusPolicyEngine(); w.Stop(); var newEngineTicks = w.ElapsedTicks; diff --git a/bindings/csharp/net4.6/Regorus.cs b/bindings/csharp/net4.6/Regorus.cs index 7d268568..bb909394 100644 --- a/bindings/csharp/net4.6/Regorus.cs +++ b/bindings/csharp/net4.6/Regorus.cs @@ -19,11 +19,11 @@ namespace Microsoft.WindowsAzure.Regorus.IaaS { - public class PolicyEngine : ICloneable, IDisposable + public class RegorusPolicyEngine : ICloneable, IDisposable { unsafe private RegorusFFI.RegorusEngine* E; - public PolicyEngine() + public RegorusPolicyEngine() { unsafe { @@ -49,7 +49,7 @@ public void Dispose() public object Clone() { - var clone = (PolicyEngine)this.MemberwiseClone(); + var clone = (RegorusPolicyEngine)this.MemberwiseClone(); unsafe { clone.E = RegorusFFI.API.regorus_engine_clone(E); diff --git a/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec b/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec index 5af0e9f8..95adefb5 100644 --- a/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec +++ b/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec @@ -2,7 +2,7 @@ RegorusCsharp-Lib-x64 - 0.0.1 + 0.0.2 RegorusCsharp-Lib-x64 yangjie@microsoft.com yangjie@microsoft.com From 48917b7b0df7ed6009c1e04437a0690882fd4ef6 Mon Sep 17 00:00:00 2001 From: mgunnala <113645315+mgunnala@users.noreply.github.com> Date: Thu, 23 May 2024 09:00:48 -0700 Subject: [PATCH 18/21] Add python tests for regorus (#4) * Add pytest * Update pytest --- .gitignore | 2 + bindings/python/test_extensions.py | 214 +++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 bindings/python/test_extensions.py diff --git a/.gitignore b/.gitignore index 33384ff6..2b94ed84 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Generated by Cargo # will have compiled files and executables /target/ +**/wheels/ +**/__pycache__/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html diff --git a/bindings/python/test_extensions.py b/bindings/python/test_extensions.py new file mode 100644 index 00000000..ef779091 --- /dev/null +++ b/bindings/python/test_extensions.py @@ -0,0 +1,214 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +import json +import pytest +import regorus + +TEST_EXT_NAME = "Microsoft.Azure.ActiveDirectory.AADSSHLoginForLinux" + + +@pytest.fixture(name="engine", scope="function") +def engine_fixture(): + """ + Fixture to handle creation and cleanup of a default policy engine. + New engine is created for each test case. + """ + engine = regorus.Engine() + engine.add_policy_from_file('../../examples/extension_list/agent_extension_policy.rego') + yield engine + + +@pytest.fixture(name="input_data") +def input_data_fixture(): + """ + Fixture to handle creation and cleanup of a default input data. + New input data is created for each test case. + """ + input_data = { + "extensions": { + TEST_EXT_NAME: { + "signingInfo": { + "extensionSigned": False + } + } + } + } + input_json = json.dumps(input_data) + yield input_json + + +@pytest.fixture(name="default_data") +def default_data_fixture(): + """Fixture for default data""" + data_json = { + "azureGuestAgentPolicy": { + "policyVersion": "0.1.0", + "signingRules": { + "extensionSigned": False + }, + "allowListOnly": False + } + } + data_json = json.dumps(data_json) + yield data_json + + +def test_default_data_json(engine, input_data): + """Test the default data in json format for extension policy.""" + data_json = { + "azureGuestAgentPolicy": { + "policyVersion": "0.1.0", + "signingRules": { + "extensionSigned": False + }, + "allowListOnly": False + } + } + data_json = json.dumps(data_json) + engine.add_data_json(data_json) + engine.set_input_json(input_data) + # Eval query + results = engine.eval_query('data.agent_extension_policy') + assert results['result'][0]['expressions'][0]['value']['extensions_to_download'][TEST_EXT_NAME]['downloadAllowed'] + + +def test_default_data_file(engine, input_data): + """Test the default data in file format for extension policy.""" + data_default_path = "../../examples/extension_list/agent-extension-default-data.json" + engine.add_data_from_json_file(data_default_path) + engine.set_input_json(input_data) + # Eval query + results = engine.eval_query('data.agent_extension_policy') + assert results['result'][0]['expressions'][0]['value']['extensions_to_download'][TEST_EXT_NAME]['downloadAllowed'] + + +def test_allow_all(engine, input_data): + """Test the policy engine with allow all policy.""" + data_json = { + "azureGuestAgentPolicy": { + "policyVersion": "0.1.0", + "signingRules": { + "extensionSigned": False + }, + "allowListOnly": False + } + } + data_json = json.dumps(data_json) + engine.add_data_json(data_json) + engine.set_input_json(input_data) + # Eval query + results = engine.eval_query('data.agent_extension_policy') + assert results['result'][0]['expressions'][0]['value']['extensions_to_download'][TEST_EXT_NAME]['downloadAllowed'] + + +def test_name_only_input(engine, default_data): + """Test input with only the extension name.""" + input_data = { + "extensions": { + TEST_EXT_NAME: { + } + } + } + input_json = json.dumps(input_data) + engine.add_data_json(default_data) + engine.set_input_json(input_json) + # Eval query + results = engine.eval_query('data.agent_extension_policy') + assert results['result'][0]['expressions'][0]['value']['extensions_to_download'][TEST_EXT_NAME]['downloadAllowed'] + + +@pytest.mark.parametrize("input_signed, extension_signed", [ + (True, True), + (True, False), + (False, True), + (False, False) +]) +def test_extension_signed_rule(engine, input_signed, extension_signed): + """ + Test extension signing rule. Engine should be able to handle + both signed and unsigned extensions, with extensionSigned rule set + to either true or false. + """ + data_json = { + "azureGuestAgentPolicy": { + "policyVersion": "0.1.0", + "signingRules": { + "extensionSigned": extension_signed + }, + "allowListOnly": False + } + } + input_data = { + "extensions": { + TEST_EXT_NAME: { + "signingInfo": { + "extensionSigned": input_signed + } + } + } + } + data_json = json.dumps(data_json) + input_data = json.dumps(input_data) + engine.add_data_json(data_json) + engine.set_input_json(input_data) + # Eval query + results = engine.eval_query('data.agent_extension_policy') + + # assert results + if extension_signed: + assert results['result'][0]['expressions'][0]['value']['extensions_validated'][TEST_EXT_NAME]['signingValidated'] == input_signed + else: + assert results['result'][0]['expressions'][0]['value']['extensions_validated'][TEST_EXT_NAME]['signingValidated'] + assert results['result'][0]['expressions'][0]['value']['extensions_to_download'][TEST_EXT_NAME]['downloadAllowed'] + + +@pytest.mark.parametrize("ext_allowed, allow_rule", [ + (True, True), + (True, False), + (False, True), + (False, False) +]) +def test_allowlist_rule(engine, ext_allowed, allow_rule): + """ + Test allowListOnly rule. Engine should be able to handle + both allowed and disallowed extensions, with allowListOnly rule + set to either true or false. + """ + if ext_allowed: + ext_name = TEST_EXT_NAME + else: + ext_name = "random_disallowed_extension" + + input_json = { + "extensions": { + ext_name: { + "signingInfo": { + "extensionSigned": False + } + } + } + } + data_json = { + "azureGuestAgentPolicy": { + "signingRules": { + "extensionSigned": False + }, + "allowListOnly": allow_rule + }, + "azureGuestExtensionsPolicy": { + "Microsoft.CPlat.Core.RunCommandLinux": { + }, + TEST_EXT_NAME: { + } + } + } + input_json = json.dumps(input_json) + data_json = json.dumps(data_json) + engine.add_data_json(data_json) + engine.set_input_json(input_json) + # Eval query + results = engine.eval_query('data.agent_extension_policy') + if allow_rule: + assert results['result'][0]['expressions'][0]['value']['extensions_to_download'][ext_name]['downloadAllowed'] == ext_allowed + else: + assert results['result'][0]['expressions'][0]['value']['extensions_to_download'][ext_name]['downloadAllowed'] From e8ebe38d1fd91dbbf332252aecb2c10704edf472 Mon Sep 17 00:00:00 2001 From: Jie Yang <112013023+yangjie-msft@users.noreply.github.com> Date: Wed, 10 Jul 2024 17:11:05 -0400 Subject: [PATCH 19/21] restructure .NET binding (#5) --- bindings/csharp/{net4.6 => net40}/Program.cs | 10 +--------- bindings/csharp/{net4.6 => net40}/README | 4 ++-- bindings/csharp/{net4.6 => net40}/Regorus.cs | 0 .../{net4.6 => net40}/RegorusCsharp-Lib-x64.nuspec | 5 ++--- bindings/csharp/{net4.6 => net40}/regorus-test.csproj | 3 +-- bindings/csharp/{ => net8.0}/Program.cs | 0 bindings/csharp/{ => net8.0}/Regorus.cs | 0 bindings/csharp/{ => net8.0}/regorus-test.csproj | 6 +++--- examples/extension_list/agent-extension-input.json | 8 ++++++++ 9 files changed, 17 insertions(+), 19 deletions(-) rename bindings/csharp/{net4.6 => net40}/Program.cs (89%) rename bindings/csharp/{net4.6 => net40}/README (59%) rename bindings/csharp/{net4.6 => net40}/Regorus.cs (100%) rename bindings/csharp/{net4.6 => net40}/RegorusCsharp-Lib-x64.nuspec (82%) rename bindings/csharp/{net4.6 => net40}/regorus-test.csproj (87%) rename bindings/csharp/{ => net8.0}/Program.cs (100%) rename bindings/csharp/{ => net8.0}/Regorus.cs (100%) rename bindings/csharp/{ => net8.0}/regorus-test.csproj (67%) diff --git a/bindings/csharp/net4.6/Program.cs b/bindings/csharp/net40/Program.cs similarity index 89% rename from bindings/csharp/net4.6/Program.cs rename to bindings/csharp/net40/Program.cs index 5f0b1e6c..058c4a46 100644 --- a/bindings/csharp/net4.6/Program.cs +++ b/bindings/csharp/net40/Program.cs @@ -1,6 +1,6 @@ using System; using System.Text; -using System.Text.Json; + using System.Diagnostics; using Microsoft.WindowsAzure.Regorus.IaaS; @@ -12,14 +12,6 @@ static void Main(string[] args) { long nanosecPerTick = (1000L * 1000L * 1000L) / Stopwatch.Frequency; var w = new Stopwatch(); - - - // Force load of modules. - { - var _e = new RegorusPolicyEngine(); - var _j = System.Text.Json.JsonDocument.Parse("{}"); - } - w.Restart(); var engine = new RegorusPolicyEngine(); diff --git a/bindings/csharp/net4.6/README b/bindings/csharp/net40/README similarity index 59% rename from bindings/csharp/net4.6/README rename to bindings/csharp/net40/README index b48dc9cf..68bf4d37 100644 --- a/bindings/csharp/net4.6/README +++ b/bindings/csharp/net40/README @@ -1,4 +1,4 @@ The Regorus C# binding library can be built via command "dotnet build". We can use the Regorus C# binding library built from this -directory to create a Nuget. This Nuget will contain the Regorus C# binding library with base class wrapper and definitions that -work for .NET4.6 and above. Note the Nuget can only be created after the binding library has been built. +directory to create a Nuget. This Nuget will contain the Regorus C# binding library with definitions that +work for .NET framework 4.0 (net40) and above. Note the Nuget can only be created after the binding library has been built. RegorusCsharp-Lib-x64.nuspec is built for x64 architecture. \ No newline at end of file diff --git a/bindings/csharp/net4.6/Regorus.cs b/bindings/csharp/net40/Regorus.cs similarity index 100% rename from bindings/csharp/net4.6/Regorus.cs rename to bindings/csharp/net40/Regorus.cs diff --git a/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec b/bindings/csharp/net40/RegorusCsharp-Lib-x64.nuspec similarity index 82% rename from bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec rename to bindings/csharp/net40/RegorusCsharp-Lib-x64.nuspec index 95adefb5..6d901957 100644 --- a/bindings/csharp/net4.6/RegorusCsharp-Lib-x64.nuspec +++ b/bindings/csharp/net40/RegorusCsharp-Lib-x64.nuspec @@ -2,20 +2,19 @@ RegorusCsharp-Lib-x64 - 0.0.2 + 0.0.3 RegorusCsharp-Lib-x64 yangjie@microsoft.com yangjie@microsoft.com https://www.microsoft.com false Regorus C# library for x64 - Initial version for Regorus C# library + remove Regorus.cs from Nuget Copyright (C) Microsoft Corp - diff --git a/bindings/csharp/net4.6/regorus-test.csproj b/bindings/csharp/net40/regorus-test.csproj similarity index 87% rename from bindings/csharp/net4.6/regorus-test.csproj rename to bindings/csharp/net40/regorus-test.csproj index 90f3a2bf..cbbfabdb 100644 --- a/bindings/csharp/net4.6/regorus-test.csproj +++ b/bindings/csharp/net40/regorus-test.csproj @@ -5,7 +5,6 @@ - @@ -14,7 +13,7 @@ Exe - net4.6.2 + net40 regorus_test regoregorus_test.Program enable diff --git a/bindings/csharp/Program.cs b/bindings/csharp/net8.0/Program.cs similarity index 100% rename from bindings/csharp/Program.cs rename to bindings/csharp/net8.0/Program.cs diff --git a/bindings/csharp/Regorus.cs b/bindings/csharp/net8.0/Regorus.cs similarity index 100% rename from bindings/csharp/Regorus.cs rename to bindings/csharp/net8.0/Regorus.cs diff --git a/bindings/csharp/regorus-test.csproj b/bindings/csharp/net8.0/regorus-test.csproj similarity index 67% rename from bindings/csharp/regorus-test.csproj rename to bindings/csharp/net8.0/regorus-test.csproj index 0267fedf..a64247c4 100644 --- a/bindings/csharp/regorus-test.csproj +++ b/bindings/csharp/net8.0/regorus-test.csproj @@ -1,10 +1,10 @@  - - + + - + diff --git a/examples/extension_list/agent-extension-input.json b/examples/extension_list/agent-extension-input.json index 9aa8d4eb..96af0f45 100644 --- a/examples/extension_list/agent-extension-input.json +++ b/examples/extension_list/agent-extension-input.json @@ -1,5 +1,13 @@ { "extensions": { + "Microsoft.Azure.ActiveDirectory.AADSSHLoginForLinux": { + "signingInfo": { + + "extensionSigned": false + + } + + }, "test2": { "signingInfo": { "extensionSigned": true From ad30657ee940cf19c5d638150874ded8eebf0df7 Mon Sep 17 00:00:00 2001 From: Jie Yang <112013023+yangjie-msft@users.noreply.github.com> Date: Thu, 11 Jul 2024 11:35:25 -0400 Subject: [PATCH 20/21] Update test-csharp.yml the test needs to change into the right dotnet directory. --- .github/workflows/test-csharp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-csharp.yml b/.github/workflows/test-csharp.yml index 67f16d1b..ce566e6b 100644 --- a/.github/workflows/test-csharp.yml +++ b/.github/workflows/test-csharp.yml @@ -19,8 +19,8 @@ jobs: - name: Build run: dotnet build - working-directory: ./bindings/csharp + working-directory: ./bindings/csharp/net8.0 - name: Run run: LD_LIBRARY_PATH=. dotnet run - working-directory: ./bindings/csharp + working-directory: ./bindings/csharp/net8.0 From 156842cb05ae7632e1fb70f3d3f8f78c2efd54c6 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 11 Jul 2024 18:45:25 +0000 Subject: [PATCH 21/21] clean up --- bindings/csharp/net8.0/Program.cs | 10 ++--- .../agent-extension-data-all.json | 19 --------- .../extension_list/extension-data-all.json | 5 --- .../extension_list/extension-data-all2.json | 5 --- .../extension_list/extension-data-empty.json | 2 - .../extension_list/extension-data-empty2.json | 4 -- examples/extension_list/extension-data.json | 15 ------- .../extension-input-newVersion.json | 20 --------- examples/extension_list/extension-input.json | 20 --------- examples/extension_list/extension_policy.rego | 42 ------------------- .../allowed_server.rego} | 0 examples/{ => server}/input.json | 0 12 files changed, 5 insertions(+), 137 deletions(-) delete mode 100644 examples/extension_list/agent-extension-data-all.json delete mode 100644 examples/extension_list/extension-data-all.json delete mode 100644 examples/extension_list/extension-data-all2.json delete mode 100644 examples/extension_list/extension-data-empty.json delete mode 100644 examples/extension_list/extension-data-empty2.json delete mode 100644 examples/extension_list/extension-data.json delete mode 100644 examples/extension_list/extension-input-newVersion.json delete mode 100644 examples/extension_list/extension-input.json delete mode 100644 examples/extension_list/extension_policy.rego rename examples/{example.rego => server/allowed_server.rego} (100%) rename examples/{ => server}/input.json (100%) diff --git a/bindings/csharp/net8.0/Program.cs b/bindings/csharp/net8.0/Program.cs index ea98a624..c2e15f78 100644 --- a/bindings/csharp/net8.0/Program.cs +++ b/bindings/csharp/net8.0/Program.cs @@ -21,10 +21,10 @@ w.Restart(); // Load policies and data. -engine.AddPolicyFromFile("../../tests/aci/framework.rego"); -engine.AddPolicyFromFile("../../tests/aci/api.rego"); -engine.AddPolicyFromFile("../../tests/aci/policy.rego"); -engine.AddDataFromJsonFile("../../tests/aci/data.json"); +engine.AddPolicyFromFile("../../../tests/aci/framework.rego"); +engine.AddPolicyFromFile("../../../tests/aci/api.rego"); +engine.AddPolicyFromFile("../../../tests/aci/policy.rego"); +engine.AddDataFromJsonFile("../../../tests/aci/data.json"); w.Stop(); @@ -34,7 +34,7 @@ w.Restart(); // Set input and eval rule. -engine.SetInputFromJsonFile("../../tests/aci/input.json"); +engine.SetInputFromJsonFile("../../../tests/aci/input.json"); var value = engine.EvalQuery("data.framework.mount_overlay"); var valueDoc = System.Text.Json.JsonDocument.Parse(value); diff --git a/examples/extension_list/agent-extension-data-all.json b/examples/extension_list/agent-extension-data-all.json deleted file mode 100644 index ecee611a..00000000 --- a/examples/extension_list/agent-extension-data-all.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "azureGuestAgentPolicy": { - "signingRules": { - "extensionSigned": true - }, - "allowListOnly": false - }, - "azureGuestExtensionsPolicy": { - "test2": { - "runtimeRules": {} - }, - "test3": { - "signingRules": { - "extensionSigned": false - }, - "runtimeRules": {} - } - } -} diff --git a/examples/extension_list/extension-data-all.json b/examples/extension_list/extension-data-all.json deleted file mode 100644 index b90be2a4..00000000 --- a/examples/extension_list/extension-data-all.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "allowed": { - "all":{} - } -} diff --git a/examples/extension_list/extension-data-all2.json b/examples/extension_list/extension-data-all2.json deleted file mode 100644 index 48202d9e..00000000 --- a/examples/extension_list/extension-data-all2.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "allowed": { - "All":{} - } -} diff --git a/examples/extension_list/extension-data-empty.json b/examples/extension_list/extension-data-empty.json deleted file mode 100644 index 2c63c085..00000000 --- a/examples/extension_list/extension-data-empty.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/examples/extension_list/extension-data-empty2.json b/examples/extension_list/extension-data-empty2.json deleted file mode 100644 index 2bdbbded..00000000 --- a/examples/extension_list/extension-data-empty2.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "allowed": { - } -} diff --git a/examples/extension_list/extension-data.json b/examples/extension_list/extension-data.json deleted file mode 100644 index fd20bba9..00000000 --- a/examples/extension_list/extension-data.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "allowed": { - "ext1": { - "version": "1.0", - "upgradable": false - }, - "ext2": { - "signature": "xyz245", - "upgradable": true - }, - "App3": { - "type": "app" - } - } -} diff --git a/examples/extension_list/extension-input-newVersion.json b/examples/extension_list/extension-input-newVersion.json deleted file mode 100644 index 6b6c3ebd..00000000 --- a/examples/extension_list/extension-input-newVersion.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "incoming": { - "ext1": { - "urls": ["url1", "url2"], - "state": "enabled", - "settings":["setting1", "setting2"], - "version": "1.1" - }, - "ext2": { - "location": "url2", - "state": "disabled", - "version": "2.0" - }, - "ext3": { - "location": "url3", - "state": "enabled", - "version": "1.0" - } - } -} diff --git a/examples/extension_list/extension-input.json b/examples/extension_list/extension-input.json deleted file mode 100644 index 5331c71e..00000000 --- a/examples/extension_list/extension-input.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "incoming": { - "ext1": { - "urls": ["url1", "url2"], - "state": "enabled", - "settings":["setting1", "setting2"], - "version": "1.0" - }, - "ext2": { - "location": "url2", - "state": "disabled", - "version": "2.0" - }, - "ext3": { - "location": "url3", - "state": "enabled", - "version": "1.0" - } - } -} diff --git a/examples/extension_list/extension_policy.rego b/examples/extension_list/extension_policy.rego deleted file mode 100644 index 00669941..00000000 --- a/examples/extension_list/extension_policy.rego +++ /dev/null @@ -1,42 +0,0 @@ -package extension_policy - -import rego.v1 - -allowed_extensions[name] := extension if { - check_all_data_allowed(data.allowed) # Checks if 'all' is a key in data.allowed - some name, input_extension in input.incoming # Assign any incoming extension name to 'name' - extension := input_extension # Assign the extension itself -} - -allowed_extensions[name] := extension if { - some name, input_extension in input.incoming - extension_is_allowed(input_extension, data.allowed, name) - extension := object.union(input_extension, data.allowed[name]) -} - -extension_is_allowed(input_data, allowed_data, name) if { - allowed_data[name] - check_optional_properties(input_data, allowed_data[name]) -} - -check_optional_properties(input_data, allowed) if { - not allowed.version -} else if { - allowed.version - input_data.version == allowed.version -} - -check_all_data_allowed(data_allowed) if { - data_allowed.all -} else if { - data_allowed.ALL -} else if { - data_allowed.All -} - -denied_extensions[name] := extension if { - not check_all_data_allowed(data.allowed) - some name, input_extension in input.incoming - not extension_is_allowed(input_extension, data.allowed, name) - extension := input_extension -} diff --git a/examples/example.rego b/examples/server/allowed_server.rego similarity index 100% rename from examples/example.rego rename to examples/server/allowed_server.rego diff --git a/examples/input.json b/examples/server/input.json similarity index 100% rename from examples/input.json rename to examples/server/input.json