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
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,16 @@ public BasicSlice(Set<Policy> policies, Set<Entity> entities) {
this(policies, entities, Collections.emptySet(), Collections.emptyList());
}


/**
* Construct a Slice from Entity and PolicySet objects.
*
* @param policySet Set of policies.
* @param entities Set of entities.
*/
@SuppressFBWarnings
public BasicSlice(PolicySet policySet, Set<Entity> entities) {
this(policySet.policies, entities, policySet.templates, policySet.templateInstantiations);
}

@Override
@SuppressFBWarnings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,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);
Expand Down Expand Up @@ -97,4 +101,6 @@ public static boolean validateTemplateLinkedPolicy(Policy p, EntityUID principal
private static native String parsePolicyJni(String policyStr) throws InternalException, NullPointerException;
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;
}
97 changes: 97 additions & 0 deletions CedarJava/src/main/java/com/cedarpolicy/model/slice/PolicySet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright 2022-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.cedarpolicy.model.slice;

import com.cedarpolicy.loader.LibraryLoader;

import com.cedarpolicy.model.exception.InternalException;

import java.util.Collections;
import java.util.List;
import java.util.Set;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

/** Policy Set containing policies in the Cedar language. */
public class PolicySet {
static {
LibraryLoader.loadLibrary();
}

/** Policy set. */
public Set<Policy> policies;

/** Template Instantiations. */
public List<TemplateInstantiation> templateInstantiations;

/** Templates. */
public Set<Policy> templates;

public PolicySet() {
this.policies = Collections.emptySet();
this.templates = Collections.emptySet();
this.templateInstantiations = Collections.emptyList();
}

public PolicySet(Set<Policy> policies) {
this.policies = policies;
this.templates = Collections.emptySet();
this.templateInstantiations = Collections.emptyList();
}

public PolicySet(Set<Policy> policies, Set<Policy> templates) {
this.policies = policies;
this.templates = templates;
this.templateInstantiations = Collections.emptyList();
}

public PolicySet(Set<Policy> policies, Set<Policy> templates, List<TemplateInstantiation> templateInstantiations) {
this.policies = policies;
this.templates = templates;
this.templateInstantiations = templateInstantiations;
}

/**
* Parse multiple policies and templates from a file into a PolicySet.
* @param filePath the path to the file containing the policies
* @return a PolicySet containing the parsed policies
* @throws InternalException
* @throws IOException
* @throws NullPointerException
*/
public static PolicySet parsePolicies(Path filePath) throws InternalException, IOException {
// Read the file contents into a String
String policiesString = Files.readString(filePath);
return parsePolicies(policiesString);
}

/**
* Parse a string containing multiple policies and templates into a PolicySet.
* @param policiesString the string containing the policies
* @return a PolicySet containing the parsed policies
* @throws InternalException
* @throws NullPointerException
*/
public static PolicySet parsePolicies(String policiesString) throws InternalException {
PolicySet policySet = parsePoliciesJni(policiesString);
return policySet;
}

private static native PolicySet parsePoliciesJni(String policiesStr) throws InternalException, NullPointerException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ public void testPoliciesStrToPretty() throws Exception {
assertEquals(formattedCedarPolicy, PolicyFormatter.policiesStrToPretty(unformattedCedarPolicy));
}

@Test
public void testPoliciesStrToPrettyMalformedCedarPolicy() throws Exception {
String malformedCedarPolicy = Files.readString(
Path.of(TEST_RESOURCES_DIR + "malformed_policy_set.cedar"));

assertThrows(InternalException.class,
() -> PolicyFormatter.policiesStrToPretty(malformedCedarPolicy));
}

@Test
public void testPoliciesStrToPrettyNullSafety() {
assertThrows(NullPointerException.class, () -> PolicyFormatter.policiesStrToPretty(null));
Expand Down
69 changes: 69 additions & 0 deletions CedarJava/src/test/java/com/cedarpolicy/PolicySetTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.cedarpolicy;

import com.cedarpolicy.model.exception.InternalException;
import com.cedarpolicy.model.slice.Policy;
import com.cedarpolicy.model.slice.PolicySet;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertEquals;

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

@Test
public void parsePoliciesTests() throws InternalException, IOException {
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
assertEquals(2, policySet.policies.stream().map(p -> p.policyID).distinct().count());
assertEquals(2, policySet.policies.size());
assertEquals(0, policySet.templates.size());
}

@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) {
assertNotNull(p.policySrc);
}
assertEquals(1, policySet.policies.size());
assertEquals(0, policySet.templates.size());
for (Policy p: policySet2.policies) {
assertNotNull(p.policySrc);
}
assertEquals(1, policySet2.policies.size());
assertEquals(0, policySet2.templates.size());
}

@Test
public void parseTemplatesTests() throws InternalException, IOException {
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) {
assertNotNull(p.policySrc);
}
assertEquals(1, policySet.templates.size());
}

@Test
public void parsePoliciesExceptionTests() throws InternalException, IOException {
assertThrows(IOException.class, () -> {
PolicySet.parsePolicies(Path.of("nonExistentFilePath.cedar"));
});
assertThrows(InternalException.class, () -> {
PolicySet.parsePolicies(Path.of(TEST_RESOURCES_DIR + "malformed_policy_set.cedar"));
});
}
}
38 changes: 35 additions & 3 deletions CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

public class PolicyTests {
@Test
public void parseStaticPolicyTests() {
assertDoesNotThrow(() -> {
var policy1 = Policy.parseStaticPolicy("permit(principal, action, resource);");
var policy2 = Policy.parseStaticPolicy("permit(principal, action, resource) when { principal has x && principal.x == 5};");
assertNotEquals(policy1.policyID.equals(policy2.policyID), true);
assertNotEquals(policy1.policyID, policy2.policyID);
});
assertThrows(InternalException.class, () -> {
Policy.parseStaticPolicy("permit();");
Expand All @@ -32,7 +34,7 @@ public void parsePolicyTemplateTests() {
assertDoesNotThrow(() -> {
String tbody = "permit(principal == ?principal, action, resource in ?resource);";
var template = Policy.parsePolicyTemplate(tbody);
assertTrue(template.policySrc.equals(tbody));
assertEquals(tbody, template.policySrc);
});
// ?resource slot shouldn't be used in the principal scope
assertThrows(InternalException.class, () -> {
Expand Down Expand Up @@ -84,4 +86,34 @@ public void validateTemplateLinkedPolicyFailsWhenExpected() {
Policy.validateTemplateLinkedPolicy(p2, 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"));
}
}
}
Loading