/*- * ============LICENSE_START======================================================= * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ package org.onap.policy.pdp.xacml.application.common; import com.att.research.xacml.std.IdentifierImpl; import com.att.research.xacml.std.StdStatusCode; import com.att.research.xacml.std.StdVersion; import com.att.research.xacml.std.dom.DOMStructureException; import com.att.research.xacml.util.FactoryException; import com.att.research.xacml.util.XACMLProperties; import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithm; import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithmFactory; import com.att.research.xacmlatt.pdp.policy.Policy; import com.att.research.xacmlatt.pdp.policy.PolicyDef; import com.att.research.xacmlatt.pdp.policy.PolicyFinder; import com.att.research.xacmlatt.pdp.policy.PolicyFinderFactory; import com.att.research.xacmlatt.pdp.policy.PolicySet; import com.att.research.xacmlatt.pdp.policy.PolicySetChild; import com.att.research.xacmlatt.pdp.policy.Target; import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef; import com.att.research.xacmlatt.pdp.std.StdPolicyFinder; import com.att.research.xacmlatt.pdp.util.ATTPDPProperties; import com.google.common.base.Splitter; import com.google.common.base.Strings; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.UUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Implements ONAP specific ability to find Policies for XACML PDP engine. * * @author pameladragosh * */ public class OnapPolicyFinderFactory extends PolicyFinderFactory { public static final String PROP_FILE = ".file"; public static final String PROP_URL = ".url"; private static Logger logger = LoggerFactory.getLogger(OnapPolicyFinderFactory.class); private List rootPolicies; private List referencedPolicies; private boolean needsInit = true; private Properties properties; /** * Empty private constructor. We do not want to create * an instance of this without giving Properties object. * * @throws OnapPolicyFinderFactoryException Exception will be thrown */ public OnapPolicyFinderFactory() throws OnapPolicyFinderFactoryException { throw new OnapPolicyFinderFactoryException("Please use the constructor with Properties object."); } /** * Constructor with properties passed. This will be preferred. * * @param properties Properties object */ public OnapPolicyFinderFactory(Properties properties) { super(properties); logger.info("Constructed using properties {}", properties); // // Save our properties // this.properties = properties; // // Here we differ from the StdPolicyFinderFactory in that we initialize right away. // We do not wait for a policy request to happen to look for and load policies. // this.init(); } /** * Loads the PolicyDef for the given String identifier by looking first * for a ".file" property associated with the ID and using that to load from a File and * looking for a ".url" property associated with the ID and using that to load from a URL. * * @param policyId the String identifier for the policy * @return a PolicyDef loaded from the given identifier */ protected PolicyDef loadPolicyDef(String policyId) { String propLocation = this.properties.getProperty(policyId + PROP_FILE); if (propLocation != null) { // // Try to load it from the file // PolicyDef policy = this.loadPolicyFileDef(propLocation); if (policy != null) { return policy; } } propLocation = this.properties.getProperty(policyId + PROP_URL); if (propLocation != null) { PolicyDef policy = this.loadPolicyUrlDef(propLocation); if (policy != null) { return policy; } } logger.error("No known location for Policy {}", policyId); return null; } protected PolicyDef loadPolicyFileDef(String propLocation) { File fileLocation = new File(propLocation); if (!fileLocation.exists()) { logger.error("Policy file {} does not exist.", fileLocation.getAbsolutePath()); return null; } if (!fileLocation.canRead()) { logger.error("Policy file {} cannot be read.", fileLocation.getAbsolutePath()); return null; } try { logger.info("Loading policy file {}", fileLocation); PolicyDef policyDef = DOMPolicyDef.load(fileLocation); if (policyDef != null) { return policyDef; } return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, "DOM Could not load policy"); } catch (DOMStructureException ex) { logger.error("Error loading policy file {}: {}", fileLocation.getAbsolutePath(), ex); return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage()); } } protected PolicyDef loadPolicyUrlDef(String propLocation) { InputStream is = null; try { URL url = new URL(propLocation); URLConnection urlConnection = url.openConnection(); OnapPolicyFinderFactory.logger.info("Loading policy file {}", url); is = urlConnection.getInputStream(); PolicyDef policyDef = DOMPolicyDef.load(is); if (policyDef != null) { return policyDef; } } catch (MalformedURLException ex) { logger.error("Invalid URL " + propLocation + ": " + ex.getMessage(), ex); } catch (IOException ex) { logger.error("IOException opening URL {}: {}{}", propLocation, ex.getMessage(), ex); } catch (DOMStructureException ex) { logger.error("Invalid Policy " + propLocation + ": " + ex.getMessage(), ex); return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage()); } finally { if (is != null) { try { is.close(); } catch (IOException e) { logger.error("Exception closing InputStream for GET of url {}: {}", propLocation, e.getMessage() + " (May be memory leak)", e); } } } return null; } /** * Finds the identifiers for all of the policies referenced by the given property name in the * XACMLProperties and loads them using the requested loading method. * * @param propertyName the String name of the property containing the list of policy identifiers * @return a List of PolicyDefs loaded from the given property name */ protected List getPolicyDefs(String propertyName) { String policyIds = this.properties.getProperty(propertyName); if (Strings.isNullOrEmpty(policyIds)) { return Collections.emptyList(); } Iterable policyIdArray = Splitter.on(',').trimResults().omitEmptyStrings().split(policyIds); if (policyIdArray == null) { return Collections.emptyList(); } List listPolicyDefs = new ArrayList<>(); for (String policyId : policyIdArray) { PolicyDef policyDef = this.loadPolicyDef(policyId); if (policyDef != null) { listPolicyDefs.add(policyDef); } } return listPolicyDefs; } protected synchronized void init() { if (this.needsInit) { logger.info("Initializing OnapPolicyFinderFactory Properties "); // // Check for property that combines root policies into one policyset // String combiningAlgorithm = properties.getProperty( ATTPDPProperties.PROP_POLICYFINDERFACTORY_COMBINEROOTPOLICIES); if (combiningAlgorithm != null) { try { logger.info("Combining root policies with {}", combiningAlgorithm); // // Find the combining algorithm // CombiningAlgorithm algorithm = CombiningAlgorithmFactory.newInstance() .getPolicyCombiningAlgorithm(new IdentifierImpl(combiningAlgorithm)); // // Create our root policy // PolicySet root = new PolicySet(); root.setIdentifier(new IdentifierImpl(UUID.randomUUID().toString())); root.setVersion(StdVersion.newInstance("1.0")); root.setTarget(new Target()); // // Set the algorithm // root.setPolicyCombiningAlgorithm(algorithm); // // Load all our root policies // for (PolicyDef policy : this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES)) { root.addChild(policy); } // // Set this policy as the root // this.rootPolicies = new ArrayList<>(); this.rootPolicies.add(root); } catch (Exception e) { logger.error("Failed to load Combining Algorithm Factory: {}", e.getLocalizedMessage()); } } else { logger.info("Loading root policies"); this.rootPolicies = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES); } this.referencedPolicies = this.getPolicyDefs(XACMLProperties.PROP_REFERENCEDPOLICIES); logger.info("Root Policies: {}", this.rootPolicies.size()); logger.info("Referenced Policies: {}", this.referencedPolicies.size()); this.needsInit = false; } } @Override public PolicyFinder getPolicyFinder() throws FactoryException { // // Force using any properties that were passed upon construction // return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, this.properties); } @Override public PolicyFinder getPolicyFinder(Properties properties) throws FactoryException { return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, properties); } }