d2e23fe44174fdc4605bb6a41fe2b966c817ce0f
[policy/xacml-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  * SPDX-License-Identifier: Apache-2.0
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.policy.pdp.xacml.application.common;
25
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;
30
31 import com.att.research.xacml.api.XACML3;
32 import com.att.research.xacml.util.XACMLPolicyWriter;
33 import java.io.ByteArrayOutputStream;
34 import java.io.File;
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;
56
57 /**
58  * Utility methods for storing policies to disk and updating Properties objects
59  * that reference policies.
60  *
61  * @author pameladragosh
62  */
63 class XacmlPolicyUtilsTest {
64     private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPolicyUtilsTest.class);
65
66     static Properties properties;
67
68     static PolicySetType rootPolicy = XacmlPolicyUtils.createEmptyPolicySet("root", XACML3.ID_POLICY_FIRST_APPLICABLE);
69
70     static Path rootPath;
71
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);
76
77     static PolicySetType policySet5 = XacmlPolicyUtils.createEmptyPolicySet(
78         "policyset1", XACML3.ID_POLICY_FIRST_APPLICABLE);
79
80     static Path path1;
81     static Path path2;
82     static Path path3;
83     static Path path4;
84
85     static Path policySetPath;
86
87     /**
88      * Temporary folder where we will store newly created policies.
89      */
90     @TempDir
91     static Path policyFolder;
92
93     /**
94      * Setup the JUnit tests by finishing creating the policies and
95      * writing them out to the temporary folder.
96      */
97     @BeforeAll
98     public static void setUp() {
99         assertThatCode(() -> {
100             //
101             // Load our test property object
102             //
103             try (InputStream is = new FileInputStream("src/test/resources/test.properties")) {
104                 properties = new Properties();
105                 properties.load(is);
106             }
107             //
108             // Change "/" to file separator in file names
109             //
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));
115                 }
116             }
117             //
118             // Save root policy
119             //
120             Path rootFile = XacmlPolicyUtils.constructUniquePolicyFilename(rootPolicy,
121                 policyFolder.toAbsolutePath());
122             LOGGER.info("Creating Root Policy {}", rootFile.toAbsolutePath());
123             rootPath = XacmlPolicyUtils.writePolicyFile(rootFile, rootPolicy);
124             //
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.
128             //
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)));
137             //
138             // Create our PolicySet
139             //
140             policySet5.setPolicySetId("policyset5");
141             policySet5.setTarget(new TargetType());
142             policySet5.setPolicyCombiningAlgId(XACML3.ID_POLICY_FIRST_APPLICABLE.stringValue());
143             ObjectFactory factory = new ObjectFactory();
144             //
145             // Add Policies 3 and 4 to the PolicySet
146             //
147             policySet5.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicy(policy1));
148             policySet5.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicy(policy2));
149             assertThat(policySet5.getPolicySetOrPolicyOrPolicySetIdReference()).hasSize(2);
150             //
151             // Save that to disk
152             //
153             File policySetFile = policyFolder.resolve("policySet5.xml").toFile();
154             LOGGER.info("Creating PolicySet {}", policySetFile.getAbsolutePath());
155             policySetPath = XACMLPolicyWriter.writePolicyFile(policySetFile.toPath(), policySet5);
156
157         }).doesNotThrowAnyException();
158     }
159
160     /**
161      * Helper method that creates a very simple Policy and Rule and saves it to disk.
162      *
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
166      */
167     private static Path createPolicyContents(PolicyType policy, String resource) {
168         //
169         // Create The Match
170         //
171         MatchType matchPolicyId = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
172             XACML3.ID_FUNCTION_STRING_EQUAL,
173             resource,
174             XACML3.ID_DATATYPE_STRING,
175             XACML3.ID_RESOURCE_RESOURCE_ID,
176             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
177         //
178         // This is our outer AnyOf - which is an OR
179         //
180         AnyOfType anyOf = new AnyOfType();
181         //
182         // Create AllOf (AND) of just Policy Id
183         //
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());
192         //
193         // Add the rule to the policy
194         //
195         policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
196         //
197         // Save it to disk
198         //
199         Path policyFile = XacmlPolicyUtils.constructUniquePolicyFilename(policy,
200             policyFolder.toAbsolutePath());
201         LOGGER.info("Creating Policy {}", policyFile.toAbsolutePath());
202         return XacmlPolicyUtils.writePolicyFile(policyFile, policy);
203     }
204
205     @Test
206     void testUncommonConditions() {
207         Path fileTemp = policyFolder.toFile().toPath();
208         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
209             XacmlPolicyUtils.writePolicyFile(fileTemp, "not a policy")
210         );
211
212         Path rootPathZ = policyFolder.toAbsolutePath();
213         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
214             XacmlPolicyUtils.constructUniquePolicyFilename("not a policy", rootPathZ)
215         );
216     }
217
218     @Test
219     void testUpdatingPolicies() {
220         assertThatCode(() -> {
221             //
222             // Just update root and policies
223             //
224             XacmlPolicyUtils.addPoliciesToXacmlRootPolicy(rootPolicy, policy1, policy2);
225             //
226             // Make sure it is correct
227             //
228             assertThat(rootPolicy.getPolicySetOrPolicyOrPolicySetIdReference()).hasSize(2);
229             //
230             // Save to disk
231             //
232             try (OutputStream os = new ByteArrayOutputStream()) {
233                 XACMLPolicyWriter.writePolicyFile(os, rootPolicy);
234                 LOGGER.debug("New Root Policy:{}{}", XacmlPolicyUtils.LINE_SEPARATOR, os);
235             }
236             //
237             // Just update root and PolicySet
238             //
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);
243             }
244         }).doesNotThrowAnyException();
245     }
246
247     @Test
248     void testRemovingReferencedProperties() {
249         //
250         // Dump what we are starting with
251         //
252         XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
253         //
254         // Remove referenced policies
255         //
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();
260
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();
265
266         //
267         // Test one that isn't in there
268         //
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();
273
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();
278
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();
283     }
284
285     @Test
286     void testRemovingRootProperties() {
287         //
288         // Dump what we are starting with
289         //
290         XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER);
291         //
292         // Remove root policies
293         //
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();
298
299         //
300         // Test one that isn't in there
301         //
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();
306     }
307
308     @Test
309     void testCopyingProperties() throws Exception {
310         //
311         // Copy to this folder
312         //
313         File copyFolder = policyFolder.resolve("copy").toFile();
314         assertTrue(copyFolder.mkdirs());
315         assertThat(copyFolder).exists();
316         //
317         // Mock up a properties object
318         //
319         Properties mockProperties = new Properties();
320         XacmlPolicyUtils.addRootPolicy(mockProperties, rootPath);
321         XacmlPolicyUtils.addReferencedPolicy(mockProperties, path1);
322         //
323         // Write the properties out to a file
324         //
325         Path fileProperties = XacmlPolicyUtils.getPropertiesPath(policyFolder.toAbsolutePath());
326         XacmlPolicyUtils.storeXacmlProperties(mockProperties, fileProperties);
327         //
328         // Now we can test the copy method
329         //
330         XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.resolve("copy/" + filename).toFile();
331         File propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents(
332             fileProperties.toAbsolutePath().toString(), mockProperties, myCreator);
333
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();
339     }
340 }