2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2023 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 * SPDX-License-Identifier: Apache-2.0
21 * ============LICENSE_END=========================================================
24 package org.onap.policy.pdp.xacml.application.common;
26 import static org.assertj.core.api.Assertions.assertThat;
27 import static org.assertj.core.api.Assertions.assertThatCode;
28 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
30 import com.att.research.xacml.api.XACML3;
31 import com.att.research.xacml.util.XACMLPolicyWriter;
32 import java.io.ByteArrayOutputStream;
34 import java.io.FileInputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.OutputStream;
38 import java.nio.file.Files;
39 import java.nio.file.Path;
40 import java.nio.file.Paths;
41 import java.util.List;
42 import java.util.Properties;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
51 import org.junit.BeforeClass;
52 import org.junit.ClassRule;
53 import org.junit.Test;
54 import org.junit.rules.TemporaryFolder;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
59 * Utility methods for storing policies to disk and updating Properties objects
60 * that reference policies.
62 * @author pameladragosh
65 public class XacmlPolicyUtilsTest {
66 private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPolicyUtilsTest.class);
68 static Properties properties;
70 static PolicySetType rootPolicy = XacmlPolicyUtils.createEmptyPolicySet("root", XACML3.ID_POLICY_FIRST_APPLICABLE);
74 static PolicyType policy1 = XacmlPolicyUtils.createEmptyPolicy("policy1", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
75 static PolicyType policy2 = XacmlPolicyUtils.createEmptyPolicy("policy2", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
76 static PolicyType policy3 = XacmlPolicyUtils.createEmptyPolicy("policy3", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
77 static PolicyType policy4 = XacmlPolicyUtils.createEmptyPolicy("policy4", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
79 static PolicySetType policySet5 = XacmlPolicyUtils.createEmptyPolicySet(
80 "policyset1", XACML3.ID_POLICY_FIRST_APPLICABLE);
87 static Path policySetPath;
90 * Temporary folder where we will store newly created policies.
93 public static TemporaryFolder policyFolder = new TemporaryFolder();
96 * Setup the JUnit tests by finishing creating the policies and
97 * writing them out to the temporary folder.
99 * @throws Exception thrown
102 public static void setUp() throws Exception {
103 assertThatCode(() -> {
105 // Load our test property object
107 try (InputStream is = new FileInputStream("src/test/resources/test.properties")) {
108 properties = new Properties();
112 // Change "/" to file separator in file names
114 if (!"/".equals(File.separator)) {
115 List<String> fileProps = properties.keySet().stream().map(Object::toString)
116 .filter(key -> key.endsWith(".file")).toList();
117 for (String fileProp : fileProps) {
118 properties.setProperty(fileProp, properties.getProperty(fileProp).replace("/", File.separator));
124 Path rootFile = XacmlPolicyUtils.constructUniquePolicyFilename(rootPolicy, policyFolder.getRoot().toPath());
125 LOGGER.info("Creating Root Policy {}", rootFile.toAbsolutePath());
126 rootPath = XacmlPolicyUtils.writePolicyFile(rootFile, rootPolicy);
128 // Create policies - Policies 1 and 2 will become references in the
129 // root policy. While Policies 3 and 4 will become references in the
130 // soon to be created PolicySet 5 below.
132 path1 = createPolicyContents(policy1, "resource1");
133 LOGGER.info(new String(Files.readAllBytes(path1)));
134 path2 = createPolicyContents(policy2, "resource2");
135 LOGGER.info(new String(Files.readAllBytes(path2)));
136 path3 = createPolicyContents(policy3, "resourc31");
137 LOGGER.info(new String(Files.readAllBytes(path3)));
138 path4 = createPolicyContents(policy4, "resource4");
139 LOGGER.info(new String(Files.readAllBytes(path4)));
141 // Create our PolicySet
143 policySet5.setPolicySetId("policyset5");
144 policySet5.setTarget(new TargetType());
145 policySet5.setPolicyCombiningAlgId(XACML3.ID_POLICY_FIRST_APPLICABLE.stringValue());
146 ObjectFactory factory = new ObjectFactory();
148 // Add Policies 3 and 4 to the PolicySet
150 policySet5.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicy(policy1));
151 policySet5.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicy(policy2));
152 assertThat(policySet5.getPolicySetOrPolicyOrPolicySetIdReference()).hasSize(2);
156 File policySetFile = policyFolder.newFile("policySet5.xml");
157 LOGGER.info("Creating PolicySet {}", policySetFile.getAbsolutePath());
158 policySetPath = XACMLPolicyWriter.writePolicyFile(policySetFile.toPath(), policySet5);
160 }).doesNotThrowAnyException();
164 * Helper method that creates a very simple Policy and Rule and saves it to disk.
166 * @param policy Policy to store contents in
167 * @param resource A simple resource id for the Target
168 * @return Path object of the policy
169 * @throws IOException If unable to write to disk
171 private static Path createPolicyContents(PolicyType policy, String resource) throws IOException {
175 MatchType matchPolicyId = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
176 XACML3.ID_FUNCTION_STRING_EQUAL,
178 XACML3.ID_DATATYPE_STRING,
179 XACML3.ID_RESOURCE_RESOURCE_ID,
180 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
182 // This is our outer AnyOf - which is an OR
184 AnyOfType anyOf = new AnyOfType();
186 // Create AllOf (AND) of just Policy Id
188 anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(matchPolicyId));
189 TargetType target = new TargetType();
190 target.getAnyOf().add(anyOf);
191 policy.setTarget(target);
192 RuleType rule = new RuleType();
193 rule.setRuleId(policy.getPolicyId() + ":rule");
194 rule.setEffect(EffectType.PERMIT);
195 rule.setTarget(new TargetType());
197 // Add the rule to the policy
199 policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
203 Path policyFile = XacmlPolicyUtils.constructUniquePolicyFilename(policy, policyFolder.getRoot().toPath());
204 LOGGER.info("Creating Policy {}", policyFile.toAbsolutePath());
205 return XacmlPolicyUtils.writePolicyFile(policyFile, policy);
209 public void testUncommonConditions() throws IOException {
210 Path fileTemp = policyFolder.newFile().toPath();
211 assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
212 XacmlPolicyUtils.writePolicyFile(fileTemp, "not a policy")
215 Path rootPath = policyFolder.getRoot().toPath();
216 assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
217 XacmlPolicyUtils.constructUniquePolicyFilename("not a policy", rootPath)
222 public void testUpdatingPolicies() {
223 assertThatCode(() -> {
225 // Just update root and policies
227 XacmlPolicyUtils.addPoliciesToXacmlRootPolicy(rootPolicy, policy1, policy2);
229 // Make sure it is correct
231 assertThat(rootPolicy.getPolicySetOrPolicyOrPolicySetIdReference()).hasSize(2);
235 try (OutputStream os = new ByteArrayOutputStream()) {
236 XACMLPolicyWriter.writePolicyFile(os, rootPolicy);
237 LOGGER.debug("New Root Policy:{}{}", XacmlPolicyUtils.LINE_SEPARATOR, os);
240 // Just update root and PolicySet
242 XacmlPolicyUtils.addPolicySetsToXacmlRootPolicy(rootPolicy, policySet5);
243 try (OutputStream os = new ByteArrayOutputStream()) {
244 XACMLPolicyWriter.writePolicyFile(os, rootPolicy);
245 LOGGER.debug("New Root Policy:{}{}", XacmlPolicyUtils.LINE_SEPARATOR, os);
247 }).doesNotThrowAnyException();
251 public void testRemovingReferencedProperties() {
253 // Dump what we are starting with
255 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
257 // Remove referenced policies
259 Path ref = Paths.get("src/test/resources/ref1.xml");
260 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
261 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
262 assertThat(properties.getProperty("refstart1.file")).isNullOrEmpty();
264 ref = Paths.get("src/test/resources/ref2.xml");
265 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
266 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
267 assertThat(properties.getProperty("refstart2.file")).isNullOrEmpty();
270 // Test one that isn't in there
272 ref = Paths.get("src/test/resources/NotThere.xml");
273 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
274 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
275 assertThat(properties.getProperty("refstart3.file")).isNotBlank();
277 ref = Paths.get("src/test/resources/ref3.xml");
278 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
279 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
280 assertThat(properties.getProperty("refstart3.file")).isNullOrEmpty();
282 ref = Paths.get("src/test/resources/ref4.xml");
283 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
284 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
285 assertThat(properties.getProperty("refstart4.file")).isNullOrEmpty();
289 public void testRemovingRootProperties() {
291 // Dump what we are starting with
293 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
295 // Remove root policies
297 Path ref = Paths.get("src/test/resources/root.xml");
298 XacmlPolicyUtils.removeRootPolicy(properties, ref);
299 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
300 assertThat(properties.getProperty("root.file")).isNullOrEmpty();
303 // Test one that isn't in there
305 ref = Paths.get("src/test/resources/NotThere.xml");
306 XacmlPolicyUtils.removeRootPolicy(properties, ref);
307 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
308 assertThat(properties.getProperty("refstart3.file")).isNotBlank();
312 public void testCopyingProperties() throws Exception {
314 // Copy to this folder
316 File copyFolder = policyFolder.newFolder("copy");
317 assertThat(copyFolder).exists();
319 // Mock up a properties object
321 Properties mockProperties = new Properties();
322 XacmlPolicyUtils.addRootPolicy(mockProperties, rootPath);
323 XacmlPolicyUtils.addReferencedPolicy(mockProperties, path1);
325 // Write the properties out to a file
327 Path fileProperties = XacmlPolicyUtils.getPropertiesPath(policyFolder.getRoot().toPath());
328 XacmlPolicyUtils.storeXacmlProperties(mockProperties, fileProperties);
330 // Now we can test the copy method
332 XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile("copy/" + filename);
333 File propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents(
334 fileProperties.toAbsolutePath().toString(), mockProperties, myCreator);
336 assertThat(propertiesFile).canRead();
337 assertThat(Path.of(copyFolder.getAbsolutePath(),
338 rootPath.getFileName().toString()).toFile()).canRead();
339 assertThat(Path.of(copyFolder.getAbsolutePath(),
340 path1.getFileName().toString()).toFile()).canRead();