Set all cross references of policy/xacml-pdp
[policy/xacml-pdp.git] / applications / common / src / main / java / org / onap / policy / pdp / xacml / application / common / OnapPolicyFinderFactory.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pdp.xacml.application.common;
22
23 import com.att.research.xacml.std.IdentifierImpl;
24 import com.att.research.xacml.std.StdStatusCode;
25 import com.att.research.xacml.std.StdVersion;
26 import com.att.research.xacml.std.dom.DOMStructureException;
27 import com.att.research.xacml.util.FactoryException;
28 import com.att.research.xacml.util.XACMLProperties;
29 import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithm;
30 import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithmFactory;
31 import com.att.research.xacmlatt.pdp.policy.Policy;
32 import com.att.research.xacmlatt.pdp.policy.PolicyDef;
33 import com.att.research.xacmlatt.pdp.policy.PolicyFinder;
34 import com.att.research.xacmlatt.pdp.policy.PolicyFinderFactory;
35 import com.att.research.xacmlatt.pdp.policy.PolicySet;
36 import com.att.research.xacmlatt.pdp.policy.PolicySetChild;
37 import com.att.research.xacmlatt.pdp.policy.Target;
38 import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef;
39 import com.att.research.xacmlatt.pdp.std.StdPolicyFinder;
40 import com.att.research.xacmlatt.pdp.util.ATTPDPProperties;
41 import com.google.common.base.Splitter;
42 import com.google.common.base.Strings;
43 import java.io.File;
44 import java.util.ArrayList;
45 import java.util.Collections;
46 import java.util.List;
47 import java.util.Properties;
48 import java.util.UUID;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * Implements ONAP specific ability to find Policies for XACML PDP engine.
54  *
55  * @author pameladragosh
56  *
57  */
58 public class OnapPolicyFinderFactory extends PolicyFinderFactory {
59
60     public static final String  PROP_FILE       = ".file";
61     public static final String  PROP_URL        = ".url";
62
63     private static Logger logger                           = LoggerFactory.getLogger(OnapPolicyFinderFactory.class);
64     private List<PolicyDef> rootPolicies;
65     private List<PolicyDef> referencedPolicies;
66     private boolean needsInit                   = true;
67
68     private Properties properties;
69
70     /**
71      * Constructor with properties passed. This will be preferred.
72      *
73      * @param properties Properties object
74      */
75     public OnapPolicyFinderFactory(Properties properties) {
76         super(properties);
77         logger.info("Constructed using properties {}", properties);
78         //
79         // Save our properties
80         //
81         this.properties = properties;
82         //
83         // Here we differ from the StdPolicyFinderFactory in that we initialize right away.
84         // We do not wait for a policy request to happen to look for and load policies.
85         //
86         this.init();
87     }
88
89     /**
90      * Loads the <code>PolicyDef</code> for the given <code>String</code> identifier by looking first
91      * for a ".file" property associated with the ID and using that to load from a <code>File</code> and
92      * looking for a ".url" property associated with the ID and using that to load from a <code>URL</code>.
93      *
94      * @param policyId the <code>String</code> identifier for the policy
95      * @return a <code>PolicyDef</code> loaded from the given identifier
96      */
97     protected PolicyDef loadPolicyDef(String policyId) {
98         String propLocation = this.properties.getProperty(policyId + PROP_FILE);
99         if (propLocation != null) {
100             //
101             // Try to load it from the file
102             //
103             PolicyDef policy = this.loadPolicyFileDef(propLocation);
104             if (policy != null) {
105                 return policy;
106             }
107         }
108
109         logger.error("No known location for Policy {}", policyId);
110         return null;
111     }
112
113     protected PolicyDef loadPolicyFileDef(String propLocation) {
114         var fileLocation   = new File(propLocation);
115         if (!fileLocation.exists()) {
116             logger.error("Policy file {} does not exist.", fileLocation.getAbsolutePath());
117             return null;
118         }
119         if (!fileLocation.canRead()) {
120             logger.error("Policy file {} cannot be read.", fileLocation.getAbsolutePath());
121             return null;
122         }
123         try {
124             logger.info("Loading policy file {}", fileLocation);
125             var policyDef = DOMPolicyDef.load(fileLocation);
126             if (policyDef != null) {
127                 return policyDef;
128             }
129             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, "DOM Could not load policy");
130         } catch (DOMStructureException ex) {
131             logger.error("Error loading policy file {}", fileLocation.getAbsolutePath(), ex);
132             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage());
133         }
134     }
135
136     /**
137      * Finds the identifiers for all of the policies referenced by the given property name in the
138      * <code>XACMLProperties</code> and loads them using the requested loading method.
139      *
140      * @param propertyName the <code>String</code> name of the property containing the list of policy identifiers
141      * @return a <code>List</code> of <code>PolicyDef</code>s loaded from the given property name
142      */
143     protected List<PolicyDef> getPolicyDefs(String propertyName) {
144         String policyIds = this.properties.getProperty(propertyName);
145         if (Strings.isNullOrEmpty(policyIds)) {
146             return Collections.emptyList();
147         }
148
149         Iterable<String> policyIdArray  = Splitter.on(',').trimResults().omitEmptyStrings().split(policyIds);
150         if (policyIdArray == null) {
151             return Collections.emptyList();
152         }
153
154         List<PolicyDef> listPolicyDefs  = new ArrayList<>();
155         for (String policyId : policyIdArray) {
156             var policyDef = this.loadPolicyDef(policyId);
157             if (policyDef != null) {
158                 listPolicyDefs.add(policyDef);
159             }
160         }
161         return listPolicyDefs;
162     }
163
164     protected synchronized void init() {
165         if (! this.needsInit) {
166             logger.info("Does not need initialization");
167             return;
168         }
169         logger.info("Initializing OnapPolicyFinderFactory Properties ");
170
171         //
172         // Check for property that combines root policies into one policyset
173         //
174         String combiningAlgorithm = properties.getProperty(
175                 ATTPDPProperties.PROP_POLICYFINDERFACTORY_COMBINEROOTPOLICIES);
176         if (combiningAlgorithm != null) {
177             try {
178                 logger.info("Combining root policies with {}", combiningAlgorithm);
179                 //
180                 // Find the combining algorithm
181                 //
182                 CombiningAlgorithm<PolicySetChild> algorithm = CombiningAlgorithmFactory.newInstance()
183                         .getPolicyCombiningAlgorithm(new IdentifierImpl(combiningAlgorithm));
184                 //
185                 // Create our root policy
186                 //
187                 var root = new PolicySet();
188                 root.setIdentifier(new IdentifierImpl(UUID.randomUUID().toString()));
189                 root.setVersion(StdVersion.newInstance("1.0"));
190                 root.setTarget(new Target());
191                 //
192                 // Set the algorithm
193                 //
194                 root.setPolicyCombiningAlgorithm(algorithm);
195                 //
196                 // Load all our root policies
197                 //
198                 for (PolicyDef policy : this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES)) {
199                     root.addChild(policy);
200                 }
201                 //
202                 // Set this policy as the root
203                 //
204                 this.rootPolicies = new ArrayList<>();
205                 this.rootPolicies.add(root);
206             } catch (Exception e) {
207                 logger.error("Failed to load Combining Algorithm Factory", e);
208             }
209         } else {
210             logger.info("Loading root policies");
211             this.rootPolicies       = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES);
212         }
213         this.referencedPolicies = this.getPolicyDefs(XACMLProperties.PROP_REFERENCEDPOLICIES);
214         logger.info("Root Policies: {}", this.rootPolicies.size());
215         logger.info("Referenced Policies: {}", this.referencedPolicies.size());
216         //
217         // Make sure we set that we don't need initialization
218         //
219         this.needsInit  = false;
220     }
221
222     @Override
223     public PolicyFinder getPolicyFinder() throws FactoryException {
224         //
225         // Force using any properties that were passed upon construction
226         //
227         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, this.properties);
228     }
229
230     @Override
231     public PolicyFinder getPolicyFinder(Properties properties) throws FactoryException {
232         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, properties);
233     }
234
235 }