diff --git a/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java b/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java index aec78c74..00e529ea 100644 --- a/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java +++ b/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java @@ -79,6 +79,10 @@ public String toString() { return "// Policy ID: " + policyID + "\n" + policySrc; } + public String toJson() throws InternalException, NullPointerException { + return toJsonJni(policySrc); + } + public static Policy parseStaticPolicy(String policyStr) throws InternalException, NullPointerException { var policyText = parsePolicyJni(policyStr); return new Policy(policyText, null); @@ -110,4 +114,6 @@ private static native String parsePolicyTemplateJni(String policyTemplateStr) throws InternalException, NullPointerException; private static native boolean validateTemplateLinkedPolicyJni(String templateText, EntityUID principal, EntityUID resource) throws InternalException, NullPointerException; + + private native String toJsonJni(String policyStr) throws InternalException, NullPointerException; } diff --git a/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java b/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java index 1e9fb17e..e1fc27f5 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java +++ b/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java @@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class PolicyTests { @Test @@ -100,4 +101,34 @@ public void validateTemplateLinkedPolicyFailsWhenExpected() { Policy.validateTemplateLinkedPolicy(p3, principal, resource); }); } + + @Test + public void staticPolicyToJsonTests() throws InternalException { + assertThrows(NullPointerException.class, () -> { + Policy p = new Policy(null, null); + p.toJson(); + }); + assertThrows(InternalException.class, () -> { + Policy p = new Policy("permit();", null); + p.toJson(); + }); + + Policy p = Policy.parseStaticPolicy("permit(principal, action, resource);"); + String actualJson = p.toJson(); + String expectedJson = "{\"effect\":\"permit\",\"principal\":{\"op\":\"All\"},\"action\":{\"op\":\"All\"}," + + "\"resource\":{\"op\":\"All\"},\"conditions\":[]}"; + assertEquals(expectedJson, actualJson); + } + + @Test + public void policyTemplateToJsonFailureTests() throws InternalException { + try { + String tbody = "permit(principal == ?principal, action, resource in ?resource);"; + Policy template = Policy.parsePolicyTemplate(tbody); + template.toJson(); + fail("Expected InternalException"); + } catch (InternalException e) { + assertTrue(e.getMessage().contains("expected a static policy, got a template containing the slot ?resource")); + } + } } diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index 3b6f331c..7587604f 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -380,6 +380,26 @@ fn validate_template_linked_policy_internal<'a>( } } +#[jni_fn("com.cedarpolicy.model.policy.Policy")] +pub fn toJsonJni<'a>(mut env: JNIEnv<'a>, _: JClass, policy_jstr: JString<'a>) -> jvalue { + match to_json_internal(&mut env, policy_jstr) { + Err(e) => jni_failed(&mut env, e.as_ref()), + Ok(policy_json) => policy_json.as_jni(), + } +} + +fn to_json_internal<'a>(env: &mut JNIEnv<'a>, policy_jstr: JString<'a>) -> Result> { + if policy_jstr.is_null() { + raise_npe(env) + } else { + let policy_jstring = env.get_string(&policy_jstr)?; + let policy_string = String::from(policy_jstring); + let policy = Policy::from_str(&policy_string)?; + let policy_json = serde_json::to_string(&policy.to_json().unwrap())?; + Ok(JValueGen::Object(env.new_string(&policy_json)?.into())) + } +} + #[jni_fn("com.cedarpolicy.value.EntityIdentifier")] pub fn getEntityIdentifierRepr<'a>(mut env: JNIEnv<'a>, _: JClass, obj: JObject<'a>) -> jvalue { match get_entity_identifier_repr_internal(&mut env, obj) {