Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CedarJava/src/main/java/com/cedarpolicy/model/Effect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.cedarpolicy.model;

/**
* Represents the effect of a Cedar policy.
*/
public enum Effect {
PERMIT,
FORBID;

/**
* Converts a string to an Effect enum value, case-insensitive.
*
* @param effectString the string value to convert
* @return the corresponding Effect enum value
* @throws NullPointerException if the effectString is null
* @throws IllegalArgumentException if the effectString doesn't match any Effect in {permit, forbid}
*/
public static Effect fromString(String effectString) {

if (effectString == null) {
throw new NullPointerException();
}

switch (effectString.toLowerCase()) {
case "permit":
return PERMIT;
case "forbid":
return FORBID;
default:
throw new IllegalArgumentException("Invalid Effect: " + effectString + ". Expected 'permit' or 'forbid'");
}
}
}

21 changes: 21 additions & 0 deletions CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.cedarpolicy.model.exception.InternalException;
import com.fasterxml.jackson.annotation.JsonProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import com.cedarpolicy.model.Effect;

import java.util.concurrent.atomic.AtomicInteger;

Expand Down Expand Up @@ -78,6 +79,24 @@ public String toString() {
return "// Policy ID: " + policyID + "\n" + policySrc;
}

/**
* Returns the effect of a policy.
*
* Determines the policy effect by attempting static policy first, then template.
* In future, it will only support static policies once new class is introduced for Template.
*
* @return The effect of the policy, either "permit" or "forbid"
* @throws InternalException
* @throws NullPointerException
*/
public Effect effect() throws InternalException, NullPointerException {
try {
return Effect.fromString(policyEffectJni(policySrc)); // Get effect for static policy
} catch (InternalException e) {
return Effect.fromString(templateEffectJni(policySrc)); // Get effect for template
}
}

/**
* Get the JSON representation of the policy. Currently only supports static policies.
*/
Expand Down Expand Up @@ -106,4 +125,6 @@ private static native String parsePolicyTemplateJni(String policyTemplateStr)

private native String toJsonJni(String policyStr) throws InternalException, NullPointerException;
private static native String fromJsonJni(String policyJsonStr) throws InternalException, NullPointerException;
private native String policyEffectJni(String policyStr) throws InternalException, NullPointerException;
private native String templateEffectJni(String policyStr) throws InternalException, NullPointerException;
}
30 changes: 30 additions & 0 deletions CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.cedarpolicy.model.exception.InternalException;
import com.cedarpolicy.model.policy.Policy;
import com.cedarpolicy.model.Effect;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
Expand Down Expand Up @@ -109,4 +110,33 @@ public void policyFromJsonTest() throws InternalException {
String actualJson = p.toJson();
assertEquals(validJson, actualJson);
}

@Test void policyEffectTest() throws InternalException {

assertThrows(NullPointerException.class, () -> {
Policy p = new Policy(null, null);
p.effect();
});

// For effects not in {permit, forbid}
assertThrows(InternalException.class, () -> {
Policy p = new Policy("perm(principal == ?principal, action, resource in ?resource);", null);
p.effect();
});

// Tests for static policies
Policy permitPolicy = new Policy("permit(principal, action, resource);", null);
assertEquals(permitPolicy.effect(), Effect.PERMIT);

Policy forbidPolicy = new Policy("forbid(principal, action, resource);", null);
assertEquals(forbidPolicy.effect(), Effect.FORBID);

// Tests for templates
Policy permitTemplate = new Policy("permit(principal == ?principal, action, resource == ?resource);", null);
assertEquals(permitTemplate.effect(), Effect.PERMIT);

Policy forbidTemplate = new Policy("forbid(principal == ?principal, action, resource == ?resource);", null);
assertEquals(forbidTemplate.effect(), Effect.FORBID);

}
}
46 changes: 46 additions & 0 deletions CedarJavaFFI/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,52 @@ fn to_json_internal<'a>(env: &mut JNIEnv<'a>, policy_jstr: JString<'a>) -> Resul
}
}

#[jni_fn("com.cedarpolicy.model.policy.Policy")]
pub fn policyEffectJni<'a>(mut env: JNIEnv<'a>, _: JClass, policy_jstr: JString<'a>) -> jvalue {
match policy_effect_jni_internal(&mut env, policy_jstr) {
Err(e) => jni_failed(&mut env, e.as_ref()),
Ok(effect) => effect.as_jni(),
}
}

fn policy_effect_jni_internal<'a>(
env: &mut JNIEnv<'a>,
policy_jstr: JString<'a>,
) -> Result<JValueOwned<'a>> {
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_effect = policy.effect().to_string();
Ok(JValueGen::Object(env.new_string(&policy_effect)?.into()))
}
}

#[jni_fn("com.cedarpolicy.model.policy.Policy")]
pub fn templateEffectJni<'a>(mut env: JNIEnv<'a>, _: JClass, policy_jstr: JString<'a>) -> jvalue {
match template_effect_jni_internal(&mut env, policy_jstr) {
Err(e) => jni_failed(&mut env, e.as_ref()),
Ok(effect) => effect.as_jni(),
}
}

fn template_effect_jni_internal<'a>(
env: &mut JNIEnv<'a>,
policy_jstr: JString<'a>,
) -> Result<JValueOwned<'a>> {
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 = Template::from_str(&policy_string)?;
let policy_effect = policy.effect().to_string();
Ok(JValueGen::Object(env.new_string(&policy_effect)?.into()))
}
}

#[jni_fn("com.cedarpolicy.model.policy.Policy")]
pub fn fromJsonJni<'a>(mut env: JNIEnv<'a>, _: JClass, policy_json_jstr: JString<'a>) -> jvalue {
match from_json_internal(&mut env, policy_json_jstr) {
Expand Down
Loading