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);
55 private XacmlPolicyUtils() {
60 * Creates an empty PolicySetType object given the id and combining algorithm. Note,there
61 * will also be an empty Target created. You can easily override that if need be.
63 * @param policyId Policy Id
64 * @param policyCombiningAlgorithm Policy Combining Algorithm
65 * @return PolicySetType object
67 public static PolicySetType createEmptyPolicySet(String policyId, Identifier policyCombiningAlgorithm) {
68 PolicySetType policy = new PolicySetType();
69 policy.setPolicySetId(policyId);
70 policy.setPolicyCombiningAlgId(policyCombiningAlgorithm.stringValue());
71 policy.setTarget(new TargetType());
76 * Creates an empty PolicySetType object given the id and combining algorithm. Note,there
77 * will also be an empty Target created. You can easily override that if need be.
79 * @param policyId Policy Id
80 * @param ruleCombiningAlgorithm Rule Combining Algorithm
81 * @return PolicyType object
83 public static PolicyType createEmptyPolicy(String policyId, Identifier ruleCombiningAlgorithm) {
84 PolicyType policy = new PolicyType();
85 policy.setPolicyId(policyId);
86 policy.setRuleCombiningAlgId(ruleCombiningAlgorithm.stringValue());
87 policy.setTarget(new TargetType());
92 * This method adds a list of PolicyType objects to a root PolicySetType as
93 * referenced policies.
95 * @param rootPolicy Root PolicySet being updated
96 * @param referencedPolicies A list of PolicyType being added as a references
97 * @return the rootPolicy PolicySet object
99 public static PolicySetType addPoliciesToXacmlRootPolicy(PolicySetType rootPolicy,
100 PolicyType... referencedPolicies) {
101 ObjectFactory factory = new ObjectFactory();
103 // Iterate each policy
105 for (PolicyType referencedPolicy : referencedPolicies) {
106 IdReferenceType reference = new IdReferenceType();
107 reference.setValue(referencedPolicy.getPolicyId());
111 rootPolicy.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicyIdReference(reference));
114 // Return the updated object
120 * This method updates a root PolicySetType by adding in a PolicyType as a reference.
122 * @param rootPolicy Root PolicySet being updated
123 * @param referencedPolicySets A list of PolicySetType being added as a references
124 * @return the rootPolicy PolicySet object
126 public static PolicySetType addPolicySetsToXacmlRootPolicy(PolicySetType rootPolicy,
127 PolicySetType... referencedPolicySets) {
128 ObjectFactory factory = new ObjectFactory();
130 // Iterate each policy
132 for (PolicySetType referencedPolicySet : referencedPolicySets) {
133 IdReferenceType reference = new IdReferenceType();
134 reference.setValue(referencedPolicySet.getPolicySetId());
138 rootPolicy.getPolicySetOrPolicyOrPolicySetIdReference().add(factory.createPolicySetIdReference(reference));
141 // Return the updated object
147 * Adds in the referenced policy to the PDP properties object.
149 * @param properties Input properties
150 * @param refPolicyPath Path to the referenced policy file
151 * @return Properties object
153 public static Properties addReferencedPolicy(Properties properties, Path refPolicyPath) {
155 // Get the current set of referenced policy ids
157 Set<String> referencedPolicies = XACMLProperties.getReferencedPolicyIDs(properties);
159 // Construct a unique id
163 String refId = "ref" + id;
164 if (referencedPolicies.contains(refId)) {
167 referencedPolicies.add(refId);
168 properties.put(refId + ".file", refPolicyPath.toAbsolutePath().toString());
173 // Set the new comma separated list
175 properties.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES,
176 referencedPolicies.stream().collect(Collectors.joining(",")));
181 * Removes a referenced policy from the Properties object. Both in the line
182 * that identifies the policy and the .file property that points to the path.
184 * @param properties Input Properties object to remove
185 * @param refPolicyPath The policy file path
186 * @return Properties object
188 public static Properties removeReferencedPolicy(Properties properties, Path refPolicyPath) {
190 // Get the current set of referenced policy ids
192 StringJoiner join = new StringJoiner(",");
193 boolean found = false;
194 Set<String> referencedPolicies = XACMLProperties.getReferencedPolicyIDs(properties);
195 for (String refPolicy : referencedPolicies) {
196 String refPolicyFile = refPolicy + ".file";
198 // If the key and value match, then it will return true
200 if (properties.remove(refPolicyFile, refPolicyPath.toString())) {
202 // Record that we actually removed it
217 // Now update the list of referenced properties
219 properties.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, join.toString());
225 * Does a debug dump of referenced and root policy values.
227 * @param properties Input Properties object
228 * @param logger Logger object to use
230 public static void debugDumpPolicyProperties(Properties properties, Logger logger) {
232 // I hate surrounding this all with an if, but by
233 // doing so I clear sonar issues with passing System.lineSeparator()
236 if (logger.isDebugEnabled()) {
238 // Get the current set of referenced policy ids
240 Set<String> rootPolicies = XACMLProperties.getRootPolicyIDs(properties);
241 logger.debug("Root Policies: {}", properties.getProperty(XACMLProperties.PROP_ROOTPOLICIES));
242 for (String root : rootPolicies) {
243 logger.debug("{}", properties.getProperty(root + ".file", "NOT FOUND"));
246 // Get the current set of referenced policy ids
248 Set<String> referencedPolicies = XACMLProperties.getReferencedPolicyIDs(properties);
249 logger.debug("Referenced Policies: {}", properties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES));
250 for (String ref : referencedPolicies) {
251 logger.debug("{}", properties.getProperty(ref + ".file", "NOT FOUND"));
257 * Constructs a unique policy filename for a given policy.
259 * <P>It could be dangerous to use policy-id and policy-version if the user
260 * gives us an invalid policy-id and policy-versions.
262 * <P>Should we append a UUID also to guarantee uniqueness?
264 * <P>How do we track that in case we need to know what policies we have loaded?
266 * @param policy PolicyType object
267 * @param path Path for policy
268 * @return Path unique file path for the Policy
270 public static Path constructUniquePolicyFilename(PolicyType policy, Path path) {
273 // Can it be possible to produce an invalid filename?
274 // Should we insert a UUID
276 String filename = policy.getPolicyId() + "_" + policy.getVersion() + ".xml";
278 // Construct the Path
280 return Paths.get(path.toAbsolutePath().toString(), filename);
284 * Load properties from given file.
286 * @throws IOException If unable to read file
288 public static Properties loadXacmlProperties(Path propertyPath) throws IOException {
289 LOGGER.debug("Loading xacml properties {}", propertyPath);
290 try (InputStream is = Files.newInputStream(propertyPath)) {
291 Properties properties = new Properties();
298 * Stores the XACML Properties to the given file location.
300 * @throws IOException If unable to store the file.
302 public static void storeXacmlProperties(Properties properties, Path propertyPath) throws IOException {
303 try (OutputStream os = Files.newOutputStream(propertyPath)) {
304 String strComments = "#";
305 properties.store(os, strComments);
310 * Appends 'xacml.properties' to a root Path object
312 * @param rootPath Root Path object
313 * @return Path to rootPath/xacml.properties file
315 public static Path getPropertiesPath(Path rootPath) {
316 return Paths.get(rootPath.toAbsolutePath().toString(), "xacml.properties");
321 * Creates an instance of PDP engine given the Properties object.
323 * @param properties Incoming Properties object
324 * @return PDPEngine instance or null if failed
326 public static PDPEngine createEngine(Properties properties) {
328 // Now initialize the XACML PDP Engine
331 PDPEngineFactory factory = PDPEngineFactory.newInstance();
332 return factory.newEngine(properties);
333 } catch (FactoryException e) {
334 LOGGER.error("Failed to create XACML PDP Engine {}", e);