2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.pdp.xacml.application.common;
25 import com.att.research.xacml.api.Identifier;
26 import com.att.research.xacml.api.pdp.PDPEngine;
27 import com.att.research.xacml.api.pdp.PDPEngineFactory;
28 import com.att.research.xacml.util.FactoryException;
29 import com.att.research.xacml.util.XACMLProperties;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34 import java.nio.file.Files;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.util.Properties;
39 import java.util.StringJoiner;
40 import java.util.stream.Collectors;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.IdReferenceType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 public class XacmlPolicyUtils {
53 private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPolicyUtils.class);
54 private static final String DOT_FILE_SUFFIX = ".file";
55 private static final String NOT_FOUND_MESSAGE = "NOT FOUND";
57 private XacmlPolicyUtils() {
62 * Creates an empty PolicySetType object given the id and combining algorithm. Note,there
63 * will also be an empty Target created. You can easily override that if need be.
65 * @param policyId Policy Id
66 * @param policyCombiningAlgorithm Policy Combining Algorithm
67 * @return PolicySetType object
69 public static PolicySetType createEmptyPolicySet(String policyId, Identifier policyCombiningAlgorithm) {
70 PolicySetType policy = new PolicySetType();
71 policy.setPolicySetId(policyId);
72 policy.setPolicyCombiningAlgId(policyCombiningAlgorithm.stringValue());
73 policy.setTarget(new TargetType());
78 * Creates an empty PolicySetType object given the id and combining algorithm. Note,there
79 * will also be an empty Target created. You can easily override that if need be.
81 * @param policyId Policy Id
82 * @param ruleCombiningAlgorithm Rule Combining Algorithm
83 * @return PolicyType object
85 public static PolicyType createEmptyPolicy(String policyId, Identifier ruleCombiningAlgorithm) {
86 PolicyType policy = new PolicyType();
87 policy.setPolicyId(policyId);
88 policy.setRuleCombiningAlgId(ruleCombiningAlgorithm.stringValue());
89 policy.setTarget(new TargetType());
94 * This method adds a list of PolicyType objects to a root PolicySetType as
95 * referenced policies.
97 * @param rootPolicy Root PolicySet being updated
98 * @param referencedPolicies A list of PolicyType being added as a references
99 * @return the rootPolicy PolicySet object
101 public static PolicySetType addPoliciesToXacmlRootPolicy(PolicySetType rootPolicy,
102 PolicyType... referencedPolicies) {
103 ObjectFactory factory = new ObjectFactory();
105 // Iterate each policy
107 for (PolicyType referencedPolicy : referencedPolicies) {
108 IdReferenceType reference = new IdReferenceType();
109 reference.setValue(referencedPolicy.getPolicyId());
113 rootPolicy.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicyIdReference(reference));
116 // Return the updated object
122 * This method updates a root PolicySetType by adding in a PolicyType as a reference.
124 * @param rootPolicy Root PolicySet being updated
125 * @param referencedPolicySets A list of PolicySetType being added as a references
126 * @return the rootPolicy PolicySet object
128 public static PolicySetType addPolicySetsToXacmlRootPolicy(PolicySetType rootPolicy,
129 PolicySetType... referencedPolicySets) {
130 ObjectFactory factory = new ObjectFactory();
132 // Iterate each policy
134 for (PolicySetType referencedPolicySet : referencedPolicySets) {
135 IdReferenceType reference = new IdReferenceType();
136 reference.setValue(referencedPolicySet.getPolicySetId());
140 rootPolicy.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicySetIdReference(reference));
143 // Return the updated object
149 * Adds in the referenced policy to the PDP properties object.
151 * @param properties Input properties
152 * @param refPolicyPath Path to the referenced policy file
153 * @return Properties object
155 public static Properties addReferencedPolicy(Properties properties, Path refPolicyPath) {
157 // Get the current set of referenced policy ids
159 Set<String> referencedPolicies = XACMLProperties.getReferencedPolicyIDs(properties);
161 // Construct a unique id
165 String refId = "ref" + id;
166 if (referencedPolicies.contains(refId)) {
169 referencedPolicies.add(refId);
170 properties.put(refId + DOT_FILE_SUFFIX, refPolicyPath.toAbsolutePath().toString());
175 // Set the new comma separated list
177 properties.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES,
178 referencedPolicies.stream().collect(Collectors.joining(",")));
183 * Removes a referenced policy from the Properties object. Both in the line
184 * that identifies the policy and the .file property that points to the path.
186 * @param properties Input Properties object to remove
187 * @param refPolicyPath The policy file path
188 * @return Properties object
190 public static Properties removeReferencedPolicy(Properties properties, Path refPolicyPath) {
192 // Get the current set of referenced policy ids
194 StringJoiner join = new StringJoiner(",");
195 boolean found = false;
196 Set<String> referencedPolicies = XACMLProperties.getReferencedPolicyIDs(properties);
197 for (String refPolicy : referencedPolicies) {
198 String refPolicyFile = refPolicy + DOT_FILE_SUFFIX;
200 // If the key and value match, then it will return true
202 if (properties.remove(refPolicyFile, refPolicyPath.toString())) {
204 // Record that we actually removed it
219 // Now update the list of referenced properties
221 properties.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, join.toString());
227 * Does a debug dump of referenced and root policy values.
229 * @param properties Input Properties object
230 * @param logger Logger object to use
232 public static void debugDumpPolicyProperties(Properties properties, Logger logger) {
234 // I hate surrounding this all with an if, but by
235 // doing so I clear sonar issues with passing System.lineSeparator()
238 if (logger.isDebugEnabled()) {
240 // Get the current set of referenced policy ids
242 Set<String> rootPolicies = XACMLProperties.getRootPolicyIDs(properties);
243 logger.debug("Root Policies: {}", properties.getProperty(XACMLProperties.PROP_ROOTPOLICIES));
244 for (String root : rootPolicies) {
245 logger.debug("{}", properties.getProperty(root + DOT_FILE_SUFFIX, NOT_FOUND_MESSAGE));
248 // Get the current set of referenced policy ids
250 Set<String> referencedPolicies = XACMLProperties.getReferencedPolicyIDs(properties);
251 logger.debug("Referenced Policies: {}", properties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES));
252 for (String ref : referencedPolicies) {
253 logger.debug("{}", properties.getProperty(ref + DOT_FILE_SUFFIX, NOT_FOUND_MESSAGE));
259 * Constructs a unique policy filename for a given policy.
261 * <P>It could be dangerous to use policy-id and policy-version if the user
262 * gives us an invalid policy-id and policy-versions.
264 * <P>Should we append a UUID also to guarantee uniqueness?
266 * <P>How do we track that in case we need to know what policies we have loaded?
268 * @param policy PolicyType object
269 * @param path Path for policy
270 * @return Path unique file path for the Policy
272 public static Path constructUniquePolicyFilename(PolicyType policy, Path path) {
275 // Can it be possible to produce an invalid filename?
276 // Should we insert a UUID
278 String filename = policy.getPolicyId() + "_" + policy.getVersion() + ".xml";
280 // Construct the Path
282 return Paths.get(path.toAbsolutePath().toString(), filename);
286 * Load properties from given file.
288 * @throws IOException If unable to read file
290 public static Properties loadXacmlProperties(Path propertyPath) throws IOException {
291 LOGGER.debug("Loading xacml properties {}", propertyPath);
292 try (InputStream is = Files.newInputStream(propertyPath)) {
293 Properties properties = new Properties();
300 * Stores the XACML Properties to the given file location.
302 * @throws IOException If unable to store the file.
304 public static void storeXacmlProperties(Properties properties, Path propertyPath) throws IOException {
305 try (OutputStream os = Files.newOutputStream(propertyPath)) {
306 String strComments = "#";
307 properties.store(os, strComments);
312 * Appends 'xacml.properties' to a root Path object
314 * @param rootPath Root Path object
315 * @return Path to rootPath/xacml.properties file
317 public static Path getPropertiesPath(Path rootPath) {
318 return Paths.get(rootPath.toAbsolutePath().toString(), "xacml.properties");
323 * Creates an instance of PDP engine given the Properties object.
325 * @param properties Incoming Properties object
326 * @return PDPEngine instance or null if failed
328 public static PDPEngine createEngine(Properties properties) {
330 // Now initialize the XACML PDP Engine
333 PDPEngineFactory factory = PDPEngineFactory.newInstance();
334 return factory.newEngine(properties);
335 } catch (FactoryException e) {
336 LOGGER.error("Failed to create XACML PDP Engine {}", e);