Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,46 @@ public static PolicySet parsePolicies(String policiesString) throws InternalExce
return policySet;
}

/**
* Parse multiple policies and templates from a JSON file into a PolicySet.
*
* <p>The file is expected to contain the JSON (EST) representation of a policy set, e.g.
* <pre>{@code
* {
* "staticPolicies": { "policy0": { ... } },
* "templates": { "template0": { ... } },
* "templateLinks": [ ... ]
* }
* }</pre>
*
* @param filePath the path to the JSON file containing the policies
* @return a PolicySet containing the parsed policies
* @throws InternalException
* @throws IOException
* @throws NullPointerException
*/
public static PolicySet parsePoliciesJson(Path filePath) throws InternalException, IOException {
// Read the file contents into a String
String policiesJsonString = Files.readString(filePath);
return parsePoliciesJson(policiesJsonString);
}

/**
* Parse a JSON string containing multiple policies and templates into a PolicySet.
*
* <p>The string is expected to be the JSON (EST) representation of a policy set. See
* {@link #parsePoliciesJson(Path)} for the expected shape.
*
* @param policiesJsonString the JSON string containing the policies
* @return a PolicySet containing the parsed policies
* @throws InternalException
* @throws NullPointerException
*/
public static PolicySet parsePoliciesJson(String policiesJsonString) throws InternalException {
PolicySet policySet = parsePoliciesJsonJni(policiesJsonString);
return policySet;
}

// --- Caching support ---

private volatile String cacheId;
Expand Down Expand Up @@ -219,6 +259,8 @@ public void run() {
}

private static native PolicySet parsePoliciesJni(String policiesStr) throws InternalException, NullPointerException;
private static native PolicySet parsePoliciesJsonJni(String policiesJsonStr)
throws InternalException, NullPointerException;
private static native String policySetToJson(String policySetStr) throws InternalException, NullPointerException;
private static native void preparsePolicySetJni(String id, String policiesJson) throws InternalException;
private static native void removeCachedPolicySetJni(String id);
Expand Down
67 changes: 67 additions & 0 deletions CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
import com.cedarpolicy.model.exception.InternalException;
import com.cedarpolicy.model.policy.Policy;
import com.cedarpolicy.model.policy.PolicySet;
import com.cedarpolicy.model.policy.TemplateLink;
import com.cedarpolicy.value.EntityUID;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;

import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -79,6 +82,70 @@ public void parseTemplatesTests() throws InternalException, IOException {
assertEquals(1, policySet.templates.size());
}

@Test
public void parsePoliciesJsonTests() throws InternalException, IOException {
PolicySet policySet = PolicySet.parsePoliciesJson(Path.of(TEST_RESOURCES_DIR + "policies.json"));
for (Policy p: policySet.policies) {
assertNotNull(p.policySrc);
}
// Make sure the policy IDs are unique as Policies are made
assertEquals(2, policySet.policies.stream().map(p -> p.policyID).distinct().count());
assertEquals(2, policySet.policies.size());
assertEquals(0, policySet.templates.size());
}

@Test
public void parsePoliciesJsonStringTests() throws InternalException {
String json = "{\"staticPolicies\":{\"policy0\":{\"effect\":\"permit\","
+ "\"principal\":{\"op\":\"All\"},\"action\":{\"op\":\"All\"},"
+ "\"resource\":{\"op\":\"All\"},\"conditions\":[]}},"
+ "\"templates\":{},\"templateLinks\":[]}";
PolicySet policySet = PolicySet.parsePoliciesJson(json);
for (Policy p: policySet.policies) {
assertNotNull(p.policySrc);
}
assertEquals(1, policySet.policies.size());
assertEquals(0, policySet.templates.size());
}

@Test
public void parseTemplatesJsonTests() throws InternalException, IOException {
PolicySet policySet = PolicySet.parsePoliciesJson(Path.of(TEST_RESOURCES_DIR + "template.json"));
for (Policy p: policySet.policies) {
assertNotNull(p.policySrc);
}
// The two static policies only; the template-linked policy is reported
// via templateLinks rather than as a static policy.
assertEquals(2, policySet.policies.size());

for (Policy p: policySet.templates) {
assertNotNull(p.policySrc);
}
assertEquals(1, policySet.templates.size());

// The template instantiation is preserved as a TemplateLink
assertEquals(1, policySet.templateLinks.size());
TemplateLink link = policySet.templateLinks.get(0);
assertEquals("Template #1", link.getTemplateId());
assertEquals("Link #1", link.getResultPolicyId());

Map<String, EntityUID> linkValues = link.getLinkValues();
assertEquals(2, linkValues.size());
assertEquals("User::\"Matt\"", linkValues.get("?principal").toString());
assertEquals("Album::\"Vacation\"", linkValues.get("?resource").toString());
}

@Test
public void parsePoliciesJsonExceptionTests() throws InternalException, IOException {
assertThrows(IOException.class, () -> {
PolicySet.parsePoliciesJson(Path.of("nonExistentFilePath.json"));
});
// Cedar policy text, not JSON, should fail to parse as JSON
assertThrows(InternalException.class, () -> {
PolicySet.parsePoliciesJson("permit(principal, action, resource);");
});
}

@Test
public void parsePoliciesExceptionTests() throws InternalException, IOException {
assertThrows(IOException.class, () -> {
Expand Down
37 changes: 37 additions & 0 deletions CedarJava/src/test/resources/policies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"staticPolicies": {
"Policy #1": {
"effect": "permit",
"principal": {
"op": "in",
"entity": { "type": "UserGroup", "id": "friends" }
},
"action": {
"op": "==",
"entity": { "type": "Action", "id": "view" }
},
"resource": {
"op": "==",
"entity": { "type": "Photo", "id": "Husky.jpg" }
},
"conditions": []
},
"Policy #2": {
"effect": "forbid",
"principal": {
"op": "==",
"entity": { "type": "User", "id": "Matt" }
},
"action": {
"op": "All"
},
"resource": {
"op": "==",
"entity": { "type": "Photo", "id": "Husky.jpg" }
},
"conditions": []
}
},
"templates": {},
"templateLinks": []
}
62 changes: 62 additions & 0 deletions CedarJava/src/test/resources/template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"staticPolicies": {
"Policy #1": {
"effect": "permit",
"principal": {
"op": "in",
"entity": { "type": "UserGroup", "id": "friends" }
},
"action": {
"op": "==",
"entity": { "type": "Action", "id": "view" }
},
"resource": {
"op": "==",
"entity": { "type": "Photo", "id": "Husky.jpg" }
},
"conditions": []
},
"Policy #2": {
"effect": "forbid",
"principal": {
"op": "==",
"entity": { "type": "User", "id": "Matt" }
},
"action": {
"op": "All"
},
"resource": {
"op": "==",
"entity": { "type": "Photo", "id": "Husky.jpg" }
},
"conditions": []
}
},
"templates": {
"Template #1": {
"effect": "permit",
"principal": {
"op": "==",
"slot": "?principal"
},
"action": {
"op": "All"
},
"resource": {
"op": "in",
"slot": "?resource"
},
"conditions": []
}
},
"templateLinks": [
{
"newId": "Link #1",
"templateId": "Template #1",
"values": {
"?principal": { "type": "User", "id": "Matt" },
"?resource": { "type": "Album", "id": "Vacation" }
}
}
]
}
Loading
Loading