2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2023-2024 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;
29 import static org.junit.jupiter.api.Assertions.assertTrue;
31 import com.att.research.xacml.api.XACML3;
32 import com.att.research.xacml.util.XACMLPolicyWriter;
33 import java.io.ByteArrayOutputStream;
35 import java.io.FileInputStream;
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.jupiter.api.BeforeAll;
52 import org.junit.jupiter.api.Test;
53 import org.junit.jupiter.api.io.TempDir;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
58 * Utility methods for storing policies to disk and updating Properties objects
59 * that reference policies.
61 * @author pameladragosh
63 class XacmlPolicyUtilsTest {
64 private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPolicyUtilsTest.class);
66 static Properties properties;
68 static PolicySetType rootPolicy = XacmlPolicyUtils.createEmptyPolicySet("root", XACML3.ID_POLICY_FIRST_APPLICABLE);
72 static PolicyType policy1 = XacmlPolicyUtils.createEmptyPolicy("policy1", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
73 static PolicyType policy2 = XacmlPolicyUtils.createEmptyPolicy("policy2", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
74 static PolicyType policy3 = XacmlPolicyUtils.createEmptyPolicy("policy3", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
75 static PolicyType policy4 = XacmlPolicyUtils.createEmptyPolicy("policy4", XACML3.ID_RULE_DENY_UNLESS_PERMIT);
77 static PolicySetType policySet5 = XacmlPolicyUtils.createEmptyPolicySet(
78 "policyset1", XACML3.ID_POLICY_FIRST_APPLICABLE);
85 static Path policySetPath;
88 * Temporary folder where we will store newly created policies.
91 static Path policyFolder;
94 * Setup the JUnit tests by finishing creating the policies and
95 * writing them out to the temporary folder.
98 public static void setUp() {
99 assertThatCode(() -> {
101 // Load our test property object
103 try (InputStream is = new FileInputStream("src/test/resources/test.properties")) {
104 properties = new Properties();
108 // Change "/" to file separator in file names
110 if (!"/".equals(File.separator)) {
111 List<String> fileProps = properties.keySet().stream().map(Object::toString)
112 .filter(key -> key.endsWith(".file")).toList();
113 for (String fileProp : fileProps) {
114 properties.setProperty(fileProp, properties.getProperty(fileProp).replace("/", File.separator));
120 Path rootFile = XacmlPolicyUtils.constructUniquePolicyFilename(rootPolicy,
121 policyFolder.toAbsolutePath());
122 LOGGER.info("Creating Root Policy {}", rootFile.toAbsolutePath());
123 rootPath = XacmlPolicyUtils.writePolicyFile(rootFile, rootPolicy);
125 // Create policies - Policies 1 and 2 will become references in the
126 // root policy. While Policies 3 and 4 will become references in the
127 // soon-to-be created PolicySet 5 below.
129 path1 = createPolicyContents(policy1, "resource1");
130 LOGGER.info(new String(Files.readAllBytes(path1)));
131 path2 = createPolicyContents(policy2, "resource2");
132 LOGGER.info(new String(Files.readAllBytes(path2)));
133 path3 = createPolicyContents(policy3, "resourc31");
134 LOGGER.info(new String(Files.readAllBytes(path3)));
135 path4 = createPolicyContents(policy4, "resource4");
136 LOGGER.info(new String(Files.readAllBytes(path4)));
138 // Create our PolicySet
140 policySet5.setPolicySetId("policyset5");
141 policySet5.setTarget(new TargetType());
142 policySet5.setPolicyCombiningAlgId(XACML3.ID_POLICY_FIRST_APPLICABLE.stringValue());
143 ObjectFactory factory = new ObjectFactory();
145 // Add Policies 3 and 4 to the PolicySet
147 policySet5.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicy(policy1));
148 policySet5.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicy(policy2));
149 assertThat(policySet5.getPolicySetOrPolicyOrPolicySetIdReference()).hasSize(2);
153 File policySetFile = policyFolder.resolve("policySet5.xml").toFile();
154 LOGGER.info("Creating PolicySet {}", policySetFile.getAbsolutePath());
155 policySetPath = XACMLPolicyWriter.writePolicyFile(policySetFile.toPath(), policySet5);
157 }).doesNotThrowAnyException();
161 * Helper method that creates a very simple Policy and Rule and saves it to disk.
163 * @param policy Policy to store contents in
164 * @param resource A simple resource id for the Target
165 * @return Path object of the policy
167 private static Path createPolicyContents(PolicyType policy, String resource) {
171 MatchType matchPolicyId = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
172 XACML3.ID_FUNCTION_STRING_EQUAL,
174 XACML3.ID_DATATYPE_STRING,
175 XACML3.ID_RESOURCE_RESOURCE_ID,
176 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
178 // This is our outer AnyOf - which is an OR
180 AnyOfType anyOf = new AnyOfType();
182 // Create AllOf (AND) of just Policy Id
184 anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(matchPolicyId));
185 TargetType target = new TargetType();
186 target.getAnyOf().add(anyOf);
187 policy.setTarget(target);
188 RuleType rule = new RuleType();
189 rule.setRuleId(policy.getPolicyId() + ":rule");
190 rule.setEffect(EffectType.PERMIT);
191 rule.setTarget(new TargetType());
193 // Add the rule to the policy
195 policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
199 Path policyFile = XacmlPolicyUtils.constructUniquePolicyFilename(policy,
200 policyFolder.toAbsolutePath());
201 LOGGER.info("Creating Policy {}", policyFile.toAbsolutePath());
202 return XacmlPolicyUtils.writePolicyFile(policyFile, policy);
206 void testUncommonConditions() {
207 Path fileTemp = policyFolder.toFile().toPath();
208 assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
209 XacmlPolicyUtils.writePolicyFile(fileTemp, "not a policy")
212 Path rootPathZ = policyFolder.toAbsolutePath();
213 assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
214 XacmlPolicyUtils.constructUniquePolicyFilename("not a policy", rootPathZ)
219 void testUpdatingPolicies() {
220 assertThatCode(() -> {
222 // Just update root and policies
224 XacmlPolicyUtils.addPoliciesToXacmlRootPolicy(rootPolicy, policy1, policy2);
226 // Make sure it is correct
228 assertThat(rootPolicy.getPolicySetOrPolicyOrPolicySetIdReference()).hasSize(2);
232 try (OutputStream os = new ByteArrayOutputStream()) {
233 XACMLPolicyWriter.writePolicyFile(os, rootPolicy);
234 LOGGER.debug("New Root Policy:{}{}", XacmlPolicyUtils.LINE_SEPARATOR, os);
237 // Just update root and PolicySet
239 XacmlPolicyUtils.addPolicySetsToXacmlRootPolicy(rootPolicy, policySet5);
240 try (OutputStream os = new ByteArrayOutputStream()) {
241 XACMLPolicyWriter.writePolicyFile(os, rootPolicy);
242 LOGGER.debug("New Root Policy:{}{}", XacmlPolicyUtils.LINE_SEPARATOR, os);
244 }).doesNotThrowAnyException();
248 void testRemovingReferencedProperties() {
250 // Dump what we are starting with
252 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
254 // Remove referenced policies
256 Path ref = Paths.get("src/test/resources/ref1.xml");
257 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
258 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
259 assertThat(properties.getProperty("refstart1.file")).isNullOrEmpty();
261 ref = Paths.get("src/test/resources/ref2.xml");
262 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
263 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
264 assertThat(properties.getProperty("refstart2.file")).isNullOrEmpty();
267 // Test one that isn't in there
269 ref = Paths.get("src/test/resources/NotThere.xml");
270 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
271 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
272 assertThat(properties.getProperty("refstart3.file")).isNotBlank();
274 ref = Paths.get("src/test/resources/ref3.xml");
275 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
276 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
277 assertThat(properties.getProperty("refstart3.file")).isNullOrEmpty();
279 ref = Paths.get("src/test/resources/ref4.xml");
280 XacmlPolicyUtils.removeReferencedPolicy(properties, ref);
281 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
282 assertThat(properties.getProperty("refstart4.file")).isNullOrEmpty();
286 void testRemovingRootProperties() {
288 // Dump what we are starting with
290 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
292 // Remove root policies
294 Path ref = Paths.get("src/test/resources/root.xml");
295 XacmlPolicyUtils.removeRootPolicy(properties, ref);
296 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
297 assertThat(properties.getProperty("root.file")).isNullOrEmpty();
300 // Test one that isn't in there
302 ref = Paths.get("src/test/resources/NotThere.xml");
303 XacmlPolicyUtils.removeRootPolicy(properties, ref);
304 XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
305 assertThat(properties.getProperty("refstart3.file")).isNotBlank();
309 void testCopyingProperties() throws Exception {
311 // Copy to this folder
313 File copyFolder = policyFolder.resolve("copy").toFile();
314 assertTrue(copyFolder.mkdirs());
315 assertThat(copyFolder).exists();
317 // Mock up a properties object
319 Properties mockProperties = new Properties();
320 XacmlPolicyUtils.addRootPolicy(mockProperties, rootPath);
321 XacmlPolicyUtils.addReferencedPolicy(mockProperties, path1);
323 // Write the properties out to a file
325 Path fileProperties = XacmlPolicyUtils.getPropertiesPath(policyFolder.toAbsolutePath());
326 XacmlPolicyUtils.storeXacmlProperties(mockProperties, fileProperties);
328 // Now we can test the copy method
330 XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.resolve("copy/" + filename).toFile();
331 File propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents(
332 fileProperties.toAbsolutePath().toString(), mockProperties, myCreator);
334 assertThat(propertiesFile).canRead();
335 assertThat(Path.of(copyFolder.getAbsolutePath(),
336 rootPath.getFileName().toString()).toFile()).canRead();
337 assertThat(Path.of(copyFolder.getAbsolutePath(),
338 path1.getFileName().toString()).toFile()).canRead();