Skip to content

Commit 80688e3

Browse files
adds PolicySet to JSON conversion (#329)
Signed-off-by: Mudit Chaudhary <chmudit@amazon.com>
1 parent 33a23e9 commit 80688e3

5 files changed

Lines changed: 299 additions & 14 deletions

File tree

CedarJava/src/main/java/com/cedarpolicy/model/policy/PolicySet.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
package com.cedarpolicy.model.policy;
1818

19+
import static com.cedarpolicy.CedarJson.objectWriter;
1920
import com.cedarpolicy.loader.LibraryLoader;
2021
import com.cedarpolicy.model.exception.InternalException;
22+
import com.fasterxml.jackson.core.JsonProcessingException;
2123

2224
import java.util.Collections;
2325
import java.util.List;
@@ -87,22 +89,33 @@ public Map<String, String> getTemplates() {
8789

8890
/**
8991
* Gets number of static policies in the Policy Set.
90-
*
92+
*
9193
* @return number of static policies, returns 0 if policies set is null
9294
*/
9395
public int getNumPolicies() {
9496
return policies != null ? policies.size() : 0;
95-
}
97+
}
9698

9799
/**
98100
* Gets number of templates in the Policy Set.
99-
*
101+
*
100102
* @return number of templates, returns 0 if templates set is null
101103
*/
102104
public int getNumTemplates() {
103105
return templates != null ? templates.size() : 0;
104106
}
105107

108+
/**
109+
* Converts the PolicySet object to a Cedar JSON string representation.
110+
*
111+
* @return Cedar JSON string representation of the PolicySet
112+
* @throws InternalException if there is an error during JSON conversion in the Rust native code
113+
* @throws JsonProcessingException if there is an error serializing the object to JSON
114+
*/
115+
public String toJson() throws InternalException, JsonProcessingException {
116+
return policySetToJson(objectWriter().writeValueAsString(this));
117+
}
118+
106119
/**
107120
* Parse multiple policies and templates from a file into a PolicySet.
108121
* @param filePath the path to the file containing the policies
@@ -130,4 +143,5 @@ public static PolicySet parsePolicies(String policiesString) throws InternalExce
130143
}
131144

132145
private static native PolicySet parsePoliciesJni(String policiesStr) throws InternalException, NullPointerException;
146+
private static native String policySetToJson(String policySetStr) throws InternalException, NullPointerException;
133147
}

CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,22 @@
2323

2424
import java.io.IOException;
2525
import java.nio.file.Path;
26+
import com.fasterxml.jackson.core.JsonProcessingException;
2627

2728
import static org.junit.jupiter.api.Assertions.assertThrows;
2829
import static org.junit.jupiter.api.Assertions.assertNotNull;
2930
import static org.junit.jupiter.api.Assertions.assertEquals;
31+
import static com.cedarpolicy.TestUtil.buildValidPolicySet;
32+
import static com.cedarpolicy.TestUtil.buildInvalidPolicySet;
3033

3134
public class PolicySetTests {
3235
private static final String TEST_RESOURCES_DIR = "src/test/resources/";
3336

3437
@Test
3538
public void parsePoliciesTests() throws InternalException, IOException {
36-
PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "policies.cedar"));
37-
for (Policy p: policySet.policies) {
39+
PolicySet policySet =
40+
PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "policies.cedar"));
41+
for (Policy p : policySet.policies) {
3842
assertNotNull(p.policySrc);
3943
}
4044
// Make sure the policy IDs are unique as Policies are made
@@ -46,13 +50,14 @@ public void parsePoliciesTests() throws InternalException, IOException {
4650
@Test
4751
public void parsePoliciesStringTests() throws InternalException {
4852
PolicySet policySet = PolicySet.parsePolicies("permit(principal, action, resource);");
49-
PolicySet policySet2 = PolicySet.parsePolicies("permit(principal, action, resource) when { principal has x && principal.x == 5};");
50-
for (Policy p: policySet.policies) {
53+
PolicySet policySet2 = PolicySet.parsePolicies(
54+
"permit(principal, action, resource) when { principal has x && principal.x == 5};");
55+
for (Policy p : policySet.policies) {
5156
assertNotNull(p.policySrc);
5257
}
5358
assertEquals(1, policySet.policies.size());
5459
assertEquals(0, policySet.templates.size());
55-
for (Policy p: policySet2.policies) {
60+
for (Policy p : policySet2.policies) {
5661
assertNotNull(p.policySrc);
5762
}
5863
assertEquals(1, policySet2.policies.size());
@@ -61,13 +66,14 @@ public void parsePoliciesStringTests() throws InternalException {
6166

6267
@Test
6368
public void parseTemplatesTests() throws InternalException, IOException {
64-
PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar"));
65-
for (Policy p: policySet.policies) {
69+
PolicySet policySet =
70+
PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar"));
71+
for (Policy p : policySet.policies) {
6672
assertNotNull(p.policySrc);
6773
}
6874
assertEquals(2, policySet.policies.size());
6975

70-
for (Policy p: policySet.templates) {
76+
for (Policy p : policySet.templates) {
7177
assertNotNull(p.policySrc);
7278
}
7379
assertEquals(1, policySet.templates.size());
@@ -96,8 +102,33 @@ public void getNumTests() throws InternalException, IOException {
96102
assertEquals(0, emptyPolicySet.getNumTemplates());
97103

98104
// Non-empty policy set
99-
PolicySet policySet = PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar"));
105+
PolicySet policySet =
106+
PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "template.cedar"));
100107
assertEquals(2, policySet.getNumPolicies());
101108
assertEquals(1, policySet.getNumTemplates());
102109
}
110+
111+
@Test
112+
public void policySetToJsonTests()
113+
throws JsonProcessingException, IOException, InternalException {
114+
// Tests valid PolicySet
115+
PolicySet validPolicySet = buildValidPolicySet();
116+
String validJson =
117+
"{\"templates\":{\"t0\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\",\"slot\":\"?principal\"},"
118+
+ "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}},"
119+
+ "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}},"
120+
+ "\"staticPolicies\":{\"p1\":{\"effect\":\"permit\",\"principal\":{\"op\":\"==\","
121+
+ "\"entity\":{\"type\":\"User\",\"id\":\"Bob\"}},"
122+
+ "\"action\":{\"op\":\"==\",\"entity\":{\"type\":\"Action\",\"id\":\"View_Photo\"}},"
123+
+ "\"resource\":{\"op\":\"in\",\"entity\":{\"type\":\"Album\",\"id\":\"Vacation\"}},\"conditions\":[]}},"
124+
+ "\"templateLinks\":[{\"templateId\":\"t0\",\"newId\":\"tl0\",\"values\":{\"?principal\":"
125+
+ "{\"__entity\":{\"type\":\"User\",\"id\":\"Alice\"}}}}]}";
126+
assertEquals(validJson, validPolicySet.toJson());
127+
128+
// Tests invalid PolicySet
129+
PolicySet invalidPolicySet = buildInvalidPolicySet();
130+
assertThrows(InternalException.class, () -> {
131+
invalidPolicySet.toJson();
132+
});
133+
}
103134
}

CedarJava/src/test/java/com/cedarpolicy/TestUtil.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,21 @@
1818

1919
import com.cedarpolicy.model.schema.Schema;
2020
import com.cedarpolicy.model.schema.Schema.JsonOrCedar;
21+
import com.cedarpolicy.model.policy.TemplateLink;
22+
import com.cedarpolicy.model.policy.PolicySet;
23+
import com.cedarpolicy.model.policy.LinkValue;
24+
import com.cedarpolicy.model.policy.Policy;
25+
import com.cedarpolicy.model.entity.Entity;
26+
import com.cedarpolicy.value.EntityTypeName;
2127

28+
import java.util.HashSet;
2229
import java.nio.charset.StandardCharsets;
2330
import java.nio.file.Files;
2431
import java.nio.file.Paths;
2532
import java.util.Optional;
33+
import java.util.ArrayList;
34+
import java.util.HashMap;
35+
import java.util.Set;
2636

2737
/** Utils to help with tests. */
2838
public final class TestUtil {
@@ -45,4 +55,57 @@ public static Schema loadSchemaResource(String schemaFile) {
4555
throw new RuntimeException("Failed to load test schema file " + schemaFile, e);
4656
}
4757
}
58+
59+
public static PolicySet buildValidPolicySet() {
60+
EntityTypeName principalType = EntityTypeName.parse("User").get();
61+
Set<Policy> policies = new HashSet<>();
62+
Set<Policy> templates = new HashSet<>();
63+
ArrayList<TemplateLink> templateLinks = new ArrayList<TemplateLink>();
64+
ArrayList<LinkValue> linkValueList = new ArrayList<>();
65+
66+
String fullPolicy =
67+
"permit(principal == User::\"Bob\", action == Action::\"View_Photo\", resource in Album::\"Vacation\");";
68+
Policy newPolicy = new Policy(fullPolicy, "p1");
69+
policies.add(newPolicy);
70+
71+
String template = "permit(principal == ?principal, action == Action::\"View_Photo\", resource in Album::\"Vacation\");";
72+
Policy policyTemplate = new Policy(template, "t0");
73+
templates.add(policyTemplate);
74+
75+
Entity principal = new Entity(principalType.of("Alice"), new HashMap<>(), new HashSet<>());
76+
LinkValue principalLinkValue = new LinkValue("?principal", principal.getEUID());
77+
linkValueList.add(principalLinkValue);
78+
79+
TemplateLink templateLink = new TemplateLink("t0", "tl0", linkValueList);
80+
templateLinks.add(templateLink);
81+
82+
return new PolicySet(policies, templates, templateLinks);
83+
}
84+
85+
public static PolicySet buildInvalidPolicySet() {
86+
EntityTypeName principalType = EntityTypeName.parse("User").get();
87+
Set<Policy> policies = new HashSet<>();
88+
Set<Policy> templates = new HashSet<>();
89+
ArrayList<TemplateLink> templateLinks = new ArrayList<TemplateLink>();
90+
ArrayList<LinkValue> linkValueList = new ArrayList<>();
91+
92+
String fullPolicy =
93+
"permit(prinipal == User::\"Bob\", action == Action::\"View_Photo\", resource in Album::\"Vacation\");";
94+
Policy newPolicy = new Policy(fullPolicy, "p1");
95+
policies.add(newPolicy);
96+
97+
String template = "permit(principal, action == Action::\"View_Photo\", resource in Album::\"Vacation\");";
98+
Policy policyTemplate = new Policy(template, "t0");
99+
templates.add(policyTemplate);
100+
101+
Entity principal = new Entity(principalType.of("Alice"), new HashMap<>(), new HashSet<>());
102+
LinkValue principalLinkValue = new LinkValue("?principal", principal.getEUID());
103+
linkValueList.add(principalLinkValue);
104+
105+
TemplateLink templateLink = new TemplateLink("t0", "tl0", linkValueList);
106+
templateLinks.add(templateLink);
107+
108+
return new PolicySet(policies, templates, templateLinks);
109+
}
110+
48111
}

0 commit comments

Comments
 (0)