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.std;
25 import com.att.research.xacml.api.Request;
26 import com.att.research.xacml.api.Response;
27 import com.att.research.xacml.api.pdp.PDPEngine;
28 import com.att.research.xacml.api.pdp.PDPEngineFactory;
29 import com.att.research.xacml.api.pdp.PDPException;
30 import com.att.research.xacml.util.FactoryException;
31 import com.att.research.xacml.util.XACMLPolicyWriter;
32 import java.io.IOException;
33 import java.nio.file.Files;
34 import java.nio.file.Path;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.List;
39 import java.util.Properties;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
41 import org.apache.commons.lang3.tuple.Pair;
42 import org.onap.policy.models.decisions.concepts.DecisionRequest;
43 import org.onap.policy.models.decisions.concepts.DecisionResponse;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
46 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
47 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
48 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
49 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
50 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
54 public abstract class StdXacmlApplicationServiceProvider implements XacmlApplicationServiceProvider {
56 private static final Logger LOGGER = LoggerFactory.getLogger(StdXacmlApplicationServiceProvider.class);
57 private Path pathForData = null;
58 private Properties pdpProperties = null;
59 private PDPEngine pdpEngine = null;
60 private Map<ToscaPolicy, Path> mapLoadedPolicies = new HashMap<>();
62 public StdXacmlApplicationServiceProvider() {
67 public String applicationName() {
68 return "Please Override";
72 public List<String> actionDecisionsSupported() {
73 return Collections.emptyList();
77 public void initialize(Path pathForData) throws XacmlApplicationException {
81 this.pathForData = pathForData;
82 LOGGER.info("New Path is {}", this.pathForData.toAbsolutePath());
84 // Look for and load the properties object
87 pdpProperties = XacmlPolicyUtils.loadXacmlProperties(XacmlPolicyUtils.getPropertiesPath(pathForData));
88 LOGGER.info("{}", pdpProperties);
89 } catch (IOException e) {
90 throw new XacmlApplicationException("Failed to load " + XacmlPolicyUtils.XACML_PROPERTY_FILE, e);
95 createEngine(pdpProperties);
99 public List<ToscaPolicyTypeIdentifier> supportedPolicyTypes() {
100 throw new UnsupportedOperationException("Please override and implement supportedPolicyTypes");
104 public boolean canSupportPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
105 throw new UnsupportedOperationException("Please override and implement canSupportPolicyType");
109 public synchronized boolean loadPolicy(ToscaPolicy toscaPolicy) {
112 // Convert the policies first
114 PolicyType xacmlPolicy = this.getTranslator(toscaPolicy.getType())
115 .convertPolicy(toscaPolicy);
116 if (xacmlPolicy == null) {
117 throw new ToscaPolicyConversionException("Failed to convert policy");
120 // Create a copy of the properties object
122 Properties newProperties = this.getProperties();
124 // Construct the filename
126 Path refPath = XacmlPolicyUtils.constructUniquePolicyFilename(xacmlPolicy, this.getDataPath());
128 // Write the policy to disk
129 // Maybe check for an error
131 XACMLPolicyWriter.writePolicyFile(refPath, xacmlPolicy);
132 if (LOGGER.isInfoEnabled()) {
133 LOGGER.info("Xacml Policy is {}{}", System.lineSeparator(), new String(Files.readAllBytes(refPath)));
136 // Add root policy to properties object
138 XacmlPolicyUtils.addRootPolicy(newProperties, refPath);
140 // Write the properties to disk
142 XacmlPolicyUtils.storeXacmlProperties(newProperties,
143 XacmlPolicyUtils.getPropertiesPath(this.getDataPath()));
147 this.createEngine(newProperties);
149 // Save the properties
151 this.pdpProperties = newProperties;
155 this.mapLoadedPolicies.put(toscaPolicy, refPath);
156 } catch (IOException | ToscaPolicyConversionException e) {
157 LOGGER.error("Failed to loadPolicies {}", e);
164 public synchronized boolean unloadPolicy(ToscaPolicy toscaPolicy) throws XacmlApplicationException {
166 // Find it in our map
168 Path refPolicy = this.mapLoadedPolicies.get(toscaPolicy);
169 if (refPolicy == null) {
170 LOGGER.error("Failed to find ToscaPolicy {} in our map size {}", toscaPolicy.getMetadata(),
171 this.mapLoadedPolicies.size());
175 // Create a copy of the properties object
177 Properties newProperties = this.getProperties();
179 // Remove it from the properties
181 XacmlPolicyUtils.removeRootPolicy(newProperties, refPolicy);
183 // We can delete the file
186 Files.delete(refPolicy);
187 } catch (IOException e) {
188 LOGGER.error("Failed to delete policy {} from disk {}", toscaPolicy.getMetadata(),
189 refPolicy.toAbsolutePath().toString(), e);
192 // Write the properties to disk
195 XacmlPolicyUtils.storeXacmlProperties(newProperties,
196 XacmlPolicyUtils.getPropertiesPath(this.getDataPath()));
197 } catch (IOException e) {
198 LOGGER.error("Failed to save the properties to disk {}", newProperties, e);
203 this.createEngine(newProperties);
205 // Save the properties
207 this.pdpProperties = newProperties;
211 if (this.mapLoadedPolicies.remove(toscaPolicy) == null) {
212 LOGGER.error("Failed to remove toscaPolicy {} from internal map size {}", toscaPolicy.getMetadata(),
213 this.mapLoadedPolicies.size());
216 // Not sure if any of the errors above warrant returning false
222 public Pair<DecisionResponse, Response> makeDecision(DecisionRequest request) {
224 // Convert to a XacmlRequest
226 Request xacmlRequest = this.getTranslator().convertRequest(request);
228 // Now get a decision
230 Response xacmlResponse = this.xacmlDecision(xacmlRequest);
232 // Convert to a DecisionResponse
234 return Pair.of(this.getTranslator().convertResponse(xacmlResponse), xacmlResponse);
237 protected abstract ToscaPolicyTranslator getTranslator(String type);
239 protected ToscaPolicyTranslator getTranslator() {
240 return this.getTranslator("");
243 protected synchronized PDPEngine getEngine() {
244 return this.pdpEngine;
247 protected synchronized Properties getProperties() {
248 Properties newProperties = new Properties();
249 newProperties.putAll(pdpProperties);
250 return newProperties;
253 protected synchronized Path getDataPath() {
258 * Creates an instance of PDP engine given the Properties object.
260 protected synchronized void createEngine(Properties properties) {
262 // Now initialize the XACML PDP Engine
265 PDPEngineFactory factory = getPdpEngineFactory();
266 PDPEngine engine = factory.newEngine(properties);
267 if (engine != null) {
268 this.pdpEngine = engine;
270 } catch (FactoryException e) {
271 LOGGER.error("Failed to create XACML PDP Engine {}", e);
276 * Make a decision call.
278 * @param request Incoming request object
279 * @return Response object
281 protected synchronized Response xacmlDecision(Request request) {
283 // This is what we need to return
285 Response response = null;
289 long timeStart = System.currentTimeMillis();
291 response = this.pdpEngine.decide(request);
292 } catch (PDPException e) {
293 LOGGER.error("Xacml PDP Engine failed {}", e);
296 // Track the end of timing
298 long timeEnd = System.currentTimeMillis();
299 LOGGER.info("Elapsed Time: {}ms", (timeEnd - timeStart));
304 // these may be overridden by junit tests
306 protected PDPEngineFactory getPdpEngineFactory() throws FactoryException {
307 return PDPEngineFactory.newInstance();