From 97023f4ebb06a1eab3bc3fa91e84b6dcabe04ba8 Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Fri, 24 Jan 2025 18:20:54 +0000 Subject: [PATCH 1/9] adds FFI functions for PolicySet.to_json Signed-off-by: Mudit Chaudhary --- CedarJavaFFI/src/interface.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index bab8845..ff89f22 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -16,6 +16,7 @@ use cedar_policy::entities_errors::EntitiesError; #[cfg(feature = "partial-eval")] use cedar_policy::ffi::is_authorized_partial_json_str; +use cedar_policy::ffi::PolicySet as PolicySetFFI; use cedar_policy::ffi::{ schema_to_json, schema_to_text, Schema as FFISchema, SchemaToJsonAnswer, SchemaToTextAnswer, }; @@ -270,6 +271,32 @@ fn parse_policy_internal<'a>( } } +#[jni_fn("com.cedarpolicy.model.policy.PolicySet")] +pub fn policySetToJson<'a>(mut env: JNIEnv<'a>, _: JClass, policies_jstr: JString<'a>) -> jvalue { + match policy_set_to_json_internal(&mut env, policies_jstr) { + Err(e) => jni_failed(&mut env, e.as_ref()), + Ok(policies_set) => policies_set.as_jni(), + } +} + +fn policy_set_to_json_internal<'a>( + env: &mut JNIEnv<'a>, + policy_set_jstr: JString<'a>, +) -> Result> { + if policy_set_jstr.is_null() { + raise_npe(env) + } else { + let policy_set_jstring = env.get_string(&policy_set_jstr)?; + let policy_set_string = String::from(policy_set_jstring); + let policy_set_ffi: PolicySetFFI = serde_json::from_str(&policy_set_string)?; + let policy_set = policy_set_ffi + .parse() + .map_err(|err| format!("Error parsing policy set: {:?}", err))?; + let policy_set_json = serde_json::to_string(&policy_set.to_json().unwrap())?; + Ok(JValueGen::Object(env.new_string(&policy_set_json)?.into())) + } +} + #[jni_fn("com.cedarpolicy.model.policy.PolicySet")] pub fn parsePoliciesJni<'a>(mut env: JNIEnv<'a>, _: JClass, policies_jstr: JString<'a>) -> jvalue { match parse_policies_internal(&mut env, policies_jstr) { From 522f56dcdfc0a49bf94a225da816e576abde7b87 Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Fri, 24 Jan 2025 17:47:32 +0000 Subject: [PATCH 2/9] modifies JSONTests to use immutable ObjectReader object instead of ObjectMapper Signed-off-by: Mudit Chaudhary --- CedarJava/src/test/java/com/cedarpolicy/JSONTests.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java b/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java index 25ceb68..e266232 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java +++ b/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java @@ -43,6 +43,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.io.IOException; import org.junit.jupiter.api.Test; @@ -256,9 +257,9 @@ public void testUnknown() { /** Tests deserialization of unknown value */ @Test - public void testDeserializationUnknown() throws JsonProcessingException { + public void testDeserializationUnknown() throws JsonProcessingException, IOException { String json = "{\"__extn\":{\"fn\":\"unknown\",\"arg\":\"test\"}}"; - Value value = CedarJson.objectMapper().readValue(json, Value.class); + Value value = CedarJson.objectReader().readValue(json, Value.class); assertInstanceOf(Unknown.class, value); Unknown unknown = (Unknown) value; assertEquals("test", unknown.toString()); @@ -266,10 +267,10 @@ public void testDeserializationUnknown() throws JsonProcessingException { /** Tests deserialization of value that causes stack overflow */ @Test - public void testDeserializationStackOverflow() { + public void testDeserializationStackOverflow() throws IOException { String json = "{\"\":" + "[".repeat(1024) + "]".repeat(1024) + "}"; try { - CedarJson.objectMapper().readValue(json, Value.class); + CedarJson.objectReader().readValue(json, Value.class); } catch (JsonProcessingException e) { System.out.println("class: " + e.getClass()); assertTrue(e instanceof StreamConstraintsException); From 1a0c049809971d43abfa4ef5ca9ff66a0654db8a Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Fri, 24 Jan 2025 19:10:22 +0000 Subject: [PATCH 3/9] adds .toJson for PolicySet Signed-off-by: Mudit Chaudhary --- .../cedarpolicy/model/policy/PolicySet.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java b/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java index 77ba8b3..7fdd8bb 100644 --- a/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java +++ b/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java @@ -16,8 +16,10 @@ package com.cedarpolicy.model.policy; +import static com.cedarpolicy.CedarJson.objectWriter; import com.cedarpolicy.loader.LibraryLoader; import com.cedarpolicy.model.exception.InternalException; +import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Collections; import java.util.List; @@ -87,22 +89,34 @@ public Map getTemplates() { /** * Gets number of static policies in the Policy Set. - * + * * @return number of static policies, returns 0 if policies set is null */ public int getNumPolicies() { return policies != null ? policies.size() : 0; - } + } /** * Gets number of templates in the Policy Set. - * + * * @return number of templates, returns 0 if templates set is null */ public int getNumTemplates() { return templates != null ? templates.size() : 0; } + /** + * Converts the PolicySet object to a Cedar JSON string representation. + * + * @return Cedar JSON string representation of the PolicySet + * @throws InternalException if there is an error during JSON conversion in the Rust native code + * @throws JsonProcessingException if there is an error serializing the object to JSON + */ + public String toJson() throws InternalException, JsonProcessingException { + String ffiCompatibleJson = objectWriter().writeValueAsString(this); + return policySetToJson(ffiCompatibleJson); + } + /** * Parse multiple policies and templates from a file into a PolicySet. * @param filePath the path to the file containing the policies @@ -130,4 +144,5 @@ public static PolicySet parsePolicies(String policiesString) throws InternalExce } private static native PolicySet parsePoliciesJni(String policiesStr) throws InternalException, NullPointerException; + private static native String policySetToJson(String policySetJStr) throws InternalException, NullPointerException; } From 5c1762e274df2e81a914c73dc74076a1d1c35c7e Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Fri, 24 Jan 2025 17:53:31 +0000 Subject: [PATCH 4/9] adds .toJson unit tests for PolicySet and corresponding test utils Signed-off-by: Mudit Chaudhary --- .../java/com/cedarpolicy/PolicySetTests.java | 25 ++++++++ .../test/java/com/cedarpolicy/TestUtil.java | 63 +++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java b/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java index b06e7bd..62f2948 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java +++ b/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java @@ -23,10 +23,13 @@ import java.io.IOException; import java.nio.file.Path; +import com.fasterxml.jackson.core.JsonProcessingException; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertEquals; +import static com.cedarpolicy.TestUtil.buildValidPolicySet; +import static com.cedarpolicy.TestUtil.buildInvalidPolicySet; public class PolicySetTests { private static final String TEST_RESOURCES_DIR = "src/test/resources/"; @@ -100,4 +103,26 @@ public void getNumTests() throws InternalException, IOException { assertEquals(2, policySet.getNumPolicies()); assertEquals(1, policySet.getNumTemplates()); } + + @Test + public void policySetToJsonTests() throws JsonProcessingException, IOException, InternalException { + // Tests valid PolicySet + PolicySet validPolicySet = buildValidPolicySet(); + String validJson = "{\"templates\":{\"t0\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\",\"slot\":\"?principal\"}," + + "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}}," + + "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}}," + + "\"staticPolicies\":{\"p1\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\"," + + "\"entity\":{\"type\":\"User\",\"id\":\"Bob\"}}," + + "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}}," + + "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}}," + + "\"templateLinks\":[{\"templateId\":\"t0\",\"newId\":\"tl0\",\"values\":{\"?principal\":" + + "{\"__entity\":{\"type\":\"User\",\"id\":\"Alice\"}}}}]}"; + assertEquals(validJson, validPolicySet.toJson()); + + // Tests invalid PolicySet + PolicySet invalidPolicySet = buildInvalidPolicySet(); + assertThrows(InternalException.class, () -> { + invalidPolicySet.toJson(); + }); + } } diff --git a/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java b/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java index 939b11d..5e4675b 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java +++ b/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java @@ -18,11 +18,21 @@ import com.cedarpolicy.model.schema.Schema; import com.cedarpolicy.model.schema.Schema.JsonOrCedar; +import com.cedarpolicy.model.policy.TemplateLink; +import com.cedarpolicy.model.policy.PolicySet; +import com.cedarpolicy.model.policy.LinkValue; +import com.cedarpolicy.model.policy.Policy; +import com.cedarpolicy.model.entity.Entity; +import com.cedarpolicy.value.EntityTypeName; +import java.util.HashSet; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Optional; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; /** Utils to help with tests. */ public final class TestUtil { @@ -45,4 +55,57 @@ public static Schema loadSchemaResource(String schemaFile) { throw new RuntimeException("Failed to load test schema file " + schemaFile, e); } } + + public static PolicySet buildValidPolicySet() { + EntityTypeName principalType = EntityTypeName.parse("User").get(); + Set policies = new HashSet<>(); + Set templates = new HashSet<>(); + ArrayList templateLinks = new ArrayList(); + ArrayList linkValueList = new ArrayList<>(); + + String fullPolicy = + "permit(principal == User::\"Bob\", action == Action::\"View_Photo\", resource in Album::\"Vacation\");"; + Policy newPolicy = new Policy(fullPolicy, "p1"); + policies.add(newPolicy); + + String template = "permit(principal == ?principal, action == Action::\"View_Photo\", resource in Album::\"Vacation\");"; + Policy policyTemplate = new Policy(template, "t0"); + templates.add(policyTemplate); + + Entity principal = new Entity(principalType.of("Alice"), new HashMap<>(), new HashSet<>()); + LinkValue principalLinkValue = new LinkValue("?principal", principal.getEUID()); + linkValueList.add(principalLinkValue); + + TemplateLink templateLink = new TemplateLink("t0", "tl0", linkValueList); + templateLinks.add(templateLink); + + return new PolicySet(policies, templates, templateLinks); + } + + public static PolicySet buildInvalidPolicySet() { + EntityTypeName principalType = EntityTypeName.parse("User").get(); + Set policies = new HashSet<>(); + Set templates = new HashSet<>(); + ArrayList templateLinks = new ArrayList(); + ArrayList linkValueList = new ArrayList<>(); + + String fullPolicy = + "permit(prinipal == User::\"Bob\", action == Action::\"View_Photo\", resource in Album::\"Vacation\");"; + Policy newPolicy = new Policy(fullPolicy, "p1"); + policies.add(newPolicy); + + String template = "permit(principal, action == Action::\"View_Photo\", resource in Album::\"Vacation\");"; + Policy policyTemplate = new Policy(template, "t0"); + templates.add(policyTemplate); + + Entity principal = new Entity(principalType.of("Alice"), new HashMap<>(), new HashSet<>()); + LinkValue principalLinkValue = new LinkValue("?principal", principal.getEUID()); + linkValueList.add(principalLinkValue); + + TemplateLink templateLink = new TemplateLink("t0", "tl0", linkValueList); + templateLinks.add(templateLink); + + return new PolicySet(policies, templates, templateLinks); + } + } From 368d6499ad8bc63a6572d50f3875fc5166e47fe5 Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Tue, 12 Aug 2025 16:05:52 -0400 Subject: [PATCH 5/9] fixes nits Signed-off-by: Mudit Chaudhary --- CedarJavaFFI/src/interface.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index ff89f22..be3a0de 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -16,9 +16,9 @@ use cedar_policy::entities_errors::EntitiesError; #[cfg(feature = "partial-eval")] use cedar_policy::ffi::is_authorized_partial_json_str; -use cedar_policy::ffi::PolicySet as PolicySetFFI; use cedar_policy::ffi::{ - schema_to_json, schema_to_text, Schema as FFISchema, SchemaToJsonAnswer, SchemaToTextAnswer, + schema_to_json, schema_to_text, PolicySet as PolicySetFFI, Schema as FFISchema, + SchemaToJsonAnswer, SchemaToTextAnswer, }; use cedar_policy::{ ffi::{is_authorized_json_str, validate_json_str}, @@ -1491,7 +1491,7 @@ pub(crate) mod jvm_based_tests { fn get_cedar_schema_internal_invalid() { let mut env = JVM.attach_current_thread().unwrap(); let json_input = r#" - + entity User = { name: String, age?: Long, From ed7018df8308746128d1c256863dcbad3d6e27ec Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Thu, 14 Aug 2025 14:53:08 -0400 Subject: [PATCH 6/9] adds FFI tests for PolicySet.toJson Signed-off-by: Mudit Chaudhary --- CedarJavaFFI/src/interface.rs | 148 ++++++++++++++++++++++++++++++++++ CedarJavaFFI/src/jlist.rs | 2 + 2 files changed, 150 insertions(+) diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index be3a0de..839ff1c 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -839,6 +839,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } #[track_caller] @@ -920,6 +921,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] fn parse_policy_internal_success_basic() { @@ -969,6 +971,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] fn parse_policy_internal_null() { @@ -980,6 +983,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] fn parse_policy_template_valid_test() { @@ -1020,6 +1024,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] fn from_json_test_valid() { @@ -1090,6 +1095,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] @@ -1188,6 +1194,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] fn template_effect_jni_internal_permit_test() { @@ -1230,6 +1237,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } } mod map_tests { @@ -1379,6 +1387,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] fn parse_cedar_schema_internal_invalid() { @@ -1431,6 +1440,7 @@ pub(crate) mod jvm_based_tests { env.exception_check().unwrap(), "Expected Java exception due to a null input" ); + env.exception_clear().unwrap(); } #[test] fn test_get_template_annotations_internal_invalid_template() { @@ -1602,4 +1612,142 @@ pub(crate) mod jvm_based_tests { ); } } + + mod policyset_tests { + use super::*; + #[test] + fn policyset_to_json_valid_test() { + let mut env = JVM.attach_current_thread().unwrap(); + let policy_set_str = r#"{ + "staticPolicies": { + "p1": "permit(principal == User::\"Bob\", action == Action::\"View_Photo\", resource in Album::\"Vacation\");" + }, + "templates": { + "t0": "permit(principal == ?principal, action == Action::\"View_Photo\", resource in Album::\"Vacation\");" + }, + "templateLinks": [{ + "templateId": "t0", + "newId": "tl0", + "values": { + "?principal": {"type": "User", "id": "Alice"} + } + }] + }"#; + + let policy_set_jstr = env.new_string(policy_set_str).unwrap(); + let policy_set_json_result = policy_set_to_json_internal(&mut env, policy_set_jstr); + + assert!(policy_set_json_result.is_ok()); + + let policy_set_json_jstr = + JString::cast(&mut env, policy_set_json_result.unwrap().l().unwrap()).unwrap(); + let actual_json_str = String::from(env.get_string(&policy_set_json_jstr).unwrap()); + + let expected_json = serde_json::json!({ + "templates": { + "t0": { + "effect": "permit", + "principal": { + "op": "==", + "slot": "?principal" + }, + "action": { + "op": "==", + "entity": { + "type": "Action", + "id": "View_Photo" + } + }, + "resource": { + "op": "in", + "entity": { + "type": "Album", + "id": "Vacation" + } + }, + "conditions": [] + } + }, + "staticPolicies": { + "p1": { + "effect": "permit", + "principal": { + "op": "==", + "entity": { + "type": "User", + "id": "Bob" + } + }, + "action": { + "op": "==", + "entity": { + "type": "Action", + "id": "View_Photo" + } + }, + "resource": { + "op": "in", + "entity": { + "type": "Album", + "id": "Vacation" + } + }, + "conditions": [] + } + }, + "templateLinks": [{ + "templateId": "t0", + "newId": "tl0", + "values": { + "?principal": { + "__entity": { + "type": "User", + "id": "Alice" + } + } + } + }] + }); + + let actual_json: serde_json::Value = serde_json::from_str(&actual_json_str) + .expect("Failed to parse actual JSON response"); + + assert_eq!( + expected_json, actual_json, + "PolicySet JSON output does not match expected structure" + ); + } + + #[test] + fn policyset_to_json_invalid_test() { + let mut env = JVM.attach_current_thread().unwrap(); + let policy_set_str = r#"{ + "staticPolicies": { + "p1": "permit(principal == User::\"Bob\", act == Action::\"View_Photo\", resrce in Album::\"Vacation\");" + }, + "templates": { + "t0": "permit(principal == ? + } + } + }"#; + + let policy_set_jstr = env.new_string(policy_set_str).unwrap(); + let policy_set_json_result = policy_set_to_json_internal(&mut env, policy_set_jstr); + + assert!( + policy_set_json_result.is_err(), + "Expected error when converting a malformed policy set" + ); + + let null_str = JString::from(JObject::null()); + let null_result = policy_set_to_json_internal(&mut env, null_str); + + assert!(null_result.is_ok(), "Expected Ok on null input"); + assert!( + env.exception_check().unwrap(), + "Expected Java exception due to a null input" + ); + env.exception_clear().unwrap(); + } + } } diff --git a/CedarJavaFFI/src/jlist.rs b/CedarJavaFFI/src/jlist.rs index f1300dd..49a3413 100644 --- a/CedarJavaFFI/src/jlist.rs +++ b/CedarJavaFFI/src/jlist.rs @@ -168,6 +168,7 @@ mod jlist_tests { let result = list.get(&mut env, 1); assert!(result.is_err()); + env.exception_clear().unwrap(); } #[test] @@ -247,6 +248,7 @@ mod jlist_tests { Ok(_) => panic!("Expected error, but got Ok"), }; assert!(result.is_err()); + env.exception_clear().unwrap(); } #[test] fn size_method_works() { From 225d4dcd394d555f90a959bcb47a3c558c14928d Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Thu, 14 Aug 2025 14:53:53 -0400 Subject: [PATCH 7/9] fixes formatting nits Signed-off-by: Mudit Chaudhary --- .../java/com/cedarpolicy/PolicySetTests.java | 46 +++++++++++-------- .../test/java/com/cedarpolicy/TestUtil.java | 4 +- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java b/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java index 62f2948..86490c5 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java +++ b/CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java @@ -36,8 +36,9 @@ public class PolicySetTests { @Test public void parsePoliciesTests() throws InternalException, IOException { - PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "policies.cedar")); - for (Policy p: policySet.policies) { + PolicySet policySet = + PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "policies.cedar")); + for (Policy p : policySet.policies) { assertNotNull(p.policySrc); } // Make sure the policy IDs are unique as Policies are made @@ -49,13 +50,14 @@ public void parsePoliciesTests() throws InternalException, IOException { @Test public void parsePoliciesStringTests() throws InternalException { PolicySet policySet = PolicySet.parsePolicies("permit(principal, action, resource);"); - PolicySet policySet2 = PolicySet.parsePolicies("permit(principal, action, resource) when { principal has x && principal.x == 5};"); - for (Policy p: policySet.policies) { + PolicySet policySet2 = PolicySet.parsePolicies( + "permit(principal, action, resource) when { principal has x && principal.x == 5};"); + for (Policy p : policySet.policies) { assertNotNull(p.policySrc); } assertEquals(1, policySet.policies.size()); assertEquals(0, policySet.templates.size()); - for (Policy p: policySet2.policies) { + for (Policy p : policySet2.policies) { assertNotNull(p.policySrc); } assertEquals(1, policySet2.policies.size()); @@ -64,13 +66,14 @@ public void parsePoliciesStringTests() throws InternalException { @Test public void parseTemplatesTests() throws InternalException, IOException { - PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar")); - for (Policy p: policySet.policies) { + PolicySet policySet = + PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar")); + for (Policy p : policySet.policies) { assertNotNull(p.policySrc); } assertEquals(2, policySet.policies.size()); - for (Policy p: policySet.templates) { + for (Policy p : policySet.templates) { assertNotNull(p.policySrc); } assertEquals(1, policySet.templates.size()); @@ -99,26 +102,29 @@ public void getNumTests() throws InternalException, IOException { assertEquals(0, emptyPolicySet.getNumTemplates()); // Non-empty policy set - PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar")); + PolicySet policySet = + PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar")); assertEquals(2, policySet.getNumPolicies()); assertEquals(1, policySet.getNumTemplates()); } @Test - public void policySetToJsonTests() throws JsonProcessingException, IOException, InternalException { + public void policySetToJsonTests() + throws JsonProcessingException, IOException, InternalException { // Tests valid PolicySet PolicySet validPolicySet = buildValidPolicySet(); - String validJson = "{\"templates\":{\"t0\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\",\"slot\":\"?principal\"}," - + "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}}," - + "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}}," - + "\"staticPolicies\":{\"p1\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\"," - + "\"entity\":{\"type\":\"User\",\"id\":\"Bob\"}}," - + "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}}," - + "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}}," - + "\"templateLinks\":[{\"templateId\":\"t0\",\"newId\":\"tl0\",\"values\":{\"?principal\":" - + "{\"__entity\":{\"type\":\"User\",\"id\":\"Alice\"}}}}]}"; + String validJson = + "{\"templates\":{\"t0\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\",\"slot\":\"?principal\"}," + + "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}}," + + "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}}," + + "\"staticPolicies\":{\"p1\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\"," + + "\"entity\":{\"type\":\"User\",\"id\":\"Bob\"}}," + + "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}}," + + "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}}," + + "\"templateLinks\":[{\"templateId\":\"t0\",\"newId\":\"tl0\",\"values\":{\"?principal\":" + + "{\"__entity\":{\"type\":\"User\",\"id\":\"Alice\"}}}}]}"; assertEquals(validJson, validPolicySet.toJson()); - + // Tests invalid PolicySet PolicySet invalidPolicySet = buildInvalidPolicySet(); assertThrows(InternalException.class, () -> { diff --git a/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java b/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java index 5e4675b..28bc3ec 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java +++ b/CedarJava/src/test/java/com/cedarpolicy/TestUtil.java @@ -60,7 +60,7 @@ public static PolicySet buildValidPolicySet() { EntityTypeName principalType = EntityTypeName.parse("User").get(); Set policies = new HashSet<>(); Set templates = new HashSet<>(); - ArrayList templateLinks = new ArrayList(); + ArrayList templateLinks = new ArrayList(); ArrayList linkValueList = new ArrayList<>(); String fullPolicy = @@ -86,7 +86,7 @@ public static PolicySet buildInvalidPolicySet() { EntityTypeName principalType = EntityTypeName.parse("User").get(); Set policies = new HashSet<>(); Set templates = new HashSet<>(); - ArrayList templateLinks = new ArrayList(); + ArrayList templateLinks = new ArrayList(); ArrayList linkValueList = new ArrayList<>(); String fullPolicy = From d2735558c7d8011582d07df94a498c34507d4536 Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Thu, 14 Aug 2025 15:00:24 -0400 Subject: [PATCH 8/9] Revert "modifies JSONTests to use immutable ObjectReader object instead of ObjectMapper" This reverts commit 522f56dcdfc0a49bf94a225da816e576abde7b87. Signed-off-by: Mudit Chaudhary --- CedarJava/src/test/java/com/cedarpolicy/JSONTests.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java b/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java index e266232..25ceb68 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java +++ b/CedarJava/src/test/java/com/cedarpolicy/JSONTests.java @@ -43,7 +43,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.io.IOException; import org.junit.jupiter.api.Test; @@ -257,9 +256,9 @@ public void testUnknown() { /** Tests deserialization of unknown value */ @Test - public void testDeserializationUnknown() throws JsonProcessingException, IOException { + public void testDeserializationUnknown() throws JsonProcessingException { String json = "{\"__extn\":{\"fn\":\"unknown\",\"arg\":\"test\"}}"; - Value value = CedarJson.objectReader().readValue(json, Value.class); + Value value = CedarJson.objectMapper().readValue(json, Value.class); assertInstanceOf(Unknown.class, value); Unknown unknown = (Unknown) value; assertEquals("test", unknown.toString()); @@ -267,10 +266,10 @@ public void testDeserializationUnknown() throws JsonProcessingException, IOExcep /** Tests deserialization of value that causes stack overflow */ @Test - public void testDeserializationStackOverflow() throws IOException { + public void testDeserializationStackOverflow() { String json = "{\"\":" + "[".repeat(1024) + "]".repeat(1024) + "}"; try { - CedarJson.objectReader().readValue(json, Value.class); + CedarJson.objectMapper().readValue(json, Value.class); } catch (JsonProcessingException e) { System.out.println("class: " + e.getClass()); assertTrue(e instanceof StreamConstraintsException); From 1b598db6060ac2e351062f15bd8ab861ad3a5ca6 Mon Sep 17 00:00:00 2001 From: Mudit Chaudhary Date: Thu, 14 Aug 2025 15:11:31 -0400 Subject: [PATCH 9/9] fixes nits Signed-off-by: Mudit Chaudhary --- .../cedarpolicy/model/policy/PolicySet.java | 5 ++--- CedarJavaFFI/src/interface.rs | 22 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java b/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java index 7fdd8bb..c980d2a 100644 --- a/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java +++ b/CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java @@ -113,8 +113,7 @@ public int getNumTemplates() { * @throws JsonProcessingException if there is an error serializing the object to JSON */ public String toJson() throws InternalException, JsonProcessingException { - String ffiCompatibleJson = objectWriter().writeValueAsString(this); - return policySetToJson(ffiCompatibleJson); + return policySetToJson(objectWriter().writeValueAsString(this)); } /** @@ -144,5 +143,5 @@ public static PolicySet parsePolicies(String policiesString) throws InternalExce } private static native PolicySet parsePoliciesJni(String policiesStr) throws InternalException, NullPointerException; - private static native String policySetToJson(String policySetJStr) throws InternalException, NullPointerException; + private static native String policySetToJson(String policySetStr) throws InternalException, NullPointerException; } diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index 839ff1c..3b8e1c0 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -1618,7 +1618,7 @@ pub(crate) mod jvm_based_tests { #[test] fn policyset_to_json_valid_test() { let mut env = JVM.attach_current_thread().unwrap(); - let policy_set_str = r#"{ + let policyset_str = r#"{ "staticPolicies": { "p1": "permit(principal == User::\"Bob\", action == Action::\"View_Photo\", resource in Album::\"Vacation\");" }, @@ -1634,14 +1634,14 @@ pub(crate) mod jvm_based_tests { }] }"#; - let policy_set_jstr = env.new_string(policy_set_str).unwrap(); - let policy_set_json_result = policy_set_to_json_internal(&mut env, policy_set_jstr); + let policyset_jstr = env.new_string(policyset_str).unwrap(); + let policyset_json_result = policy_set_to_json_internal(&mut env, policyset_jstr); - assert!(policy_set_json_result.is_ok()); + assert!(policyset_json_result.is_ok()); - let policy_set_json_jstr = - JString::cast(&mut env, policy_set_json_result.unwrap().l().unwrap()).unwrap(); - let actual_json_str = String::from(env.get_string(&policy_set_json_jstr).unwrap()); + let policyset_json_jstr = + JString::cast(&mut env, policyset_json_result.unwrap().l().unwrap()).unwrap(); + let actual_json_str = String::from(env.get_string(&policyset_json_jstr).unwrap()); let expected_json = serde_json::json!({ "templates": { @@ -1721,7 +1721,7 @@ pub(crate) mod jvm_based_tests { #[test] fn policyset_to_json_invalid_test() { let mut env = JVM.attach_current_thread().unwrap(); - let policy_set_str = r#"{ + let policyset_str = r#"{ "staticPolicies": { "p1": "permit(principal == User::\"Bob\", act == Action::\"View_Photo\", resrce in Album::\"Vacation\");" }, @@ -1731,11 +1731,11 @@ pub(crate) mod jvm_based_tests { } }"#; - let policy_set_jstr = env.new_string(policy_set_str).unwrap(); - let policy_set_json_result = policy_set_to_json_internal(&mut env, policy_set_jstr); + let policyset_jstr = env.new_string(policyset_str).unwrap(); + let policyset_json_result = policy_set_to_json_internal(&mut env, policyset_jstr); assert!( - policy_set_json_result.is_err(), + policyset_json_result.is_err(), "Expected error when converting a malformed policy set" );