Monitoring policy creation foundation
[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 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
22 package org.onap.policy.pdp.xacml.application.common;
23
24 import com.att.research.xacml.std.StdStatusCode;
25 import com.att.research.xacml.std.dom.DOMStructureException;
26 import com.att.research.xacml.util.FactoryException;
27 import com.att.research.xacml.util.XACMLProperties;
28 import com.att.research.xacmlatt.pdp.policy.Policy;
29 import com.att.research.xacmlatt.pdp.policy.PolicyDef;
30 import com.att.research.xacmlatt.pdp.policy.PolicyFinder;
31 import com.att.research.xacmlatt.pdp.policy.PolicyFinderFactory;
32 import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef;
33 import com.att.research.xacmlatt.pdp.std.StdPolicyFinder;
34 import com.google.common.base.Splitter;
35 import com.google.common.base.Strings;
36
37 import java.io.File;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.net.MalformedURLException;
41 import java.net.URL;
42 import java.net.URLConnection;
43 import java.util.ArrayList;
44 import java.util.Collections;
45 import java.util.List;
46 import java.util.Properties;
47
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 /**
52  * Implements ONAP specific ability to find Policies for XACML PDP engine.
53  *
54  * @author pameladragosh
55  *
56  */
57 public class OnapPolicyFinderFactory extends PolicyFinderFactory {
58
59     public static final String  PROP_FILE       = ".file";
60     public static final String  PROP_URL        = ".url";
61
62     private static Logger logger                           = LoggerFactory.getLogger(OnapPolicyFinderFactory.class);
63     private List<PolicyDef> rootPolicies;
64     private List<PolicyDef> referencedPolicies;
65     private boolean needsInit                   = true;
66
67     private Properties properties = null;
68
69     /**
70      * Empty constructor.
71      */
72     public OnapPolicyFinderFactory() {
73         logger.debug("Constructed without properties");
74         //
75         // Here we differ from the StdPolicyFinderFactory in that we initialize right away.
76         // We do not wait for a policy request to happen to look for and load policies.
77         //
78         this.init();
79     }
80
81     /**
82      * Constructor with properties passed. This will be preferred.
83      *
84      * @param properties Properties object
85      */
86     public OnapPolicyFinderFactory(Properties properties) {
87         super(properties);
88         logger.debug("Constructed using properties {}", properties);
89         //
90         // Save our properties
91         //
92         this.properties = properties;
93         //
94         // Here we differ from the StdPolicyFinderFactory in that we initialize right away.
95         // We do not wait for a policy request to happen to look for and load policies.
96         //
97         this.init();
98     }
99
100     /**
101      * Loads the <code>PolicyDef</code> for the given <code>String</code> identifier by looking first
102      * for a ".file" property associated with the ID and using that to load from a <code>File</code> and
103      * looking for a ".url" property associated with the ID and using that to load from a <code>URL</code>.
104      *
105      * @param policyId the <code>String</code> identifier for the policy
106      * @return a <code>PolicyDef</code> loaded from the given identifier
107      */
108     protected PolicyDef loadPolicyDef(String policyId) {
109         String propLocation = null;
110         if (this.properties == null) {
111             propLocation    = XACMLProperties.getProperty(policyId + PROP_FILE);
112         } else {
113             propLocation    = this.properties.getProperty(policyId + PROP_FILE);
114         }
115         if (propLocation != null) {
116             //
117             // Try to load it from the file
118             //
119             PolicyDef policy = this.loadPolicyFileDef(propLocation);
120             if (policy != null) {
121                 return policy;
122             }
123         }
124         if (this.properties == null) {
125             propLocation = XACMLProperties.getProperty(policyId + PROP_URL);
126         } else {
127             propLocation = this.properties.getProperty(policyId + PROP_URL);
128         }
129         if (propLocation != null) {
130             PolicyDef policy = this.loadPolicyUrlDef(propLocation);
131             if (policy != null) {
132                 return policy;
133             }
134         }
135
136         logger.error("No known location for Policy {}", policyId);
137         return null;
138     }
139
140     protected PolicyDef loadPolicyFileDef(String propLocation) {
141         File fileLocation   = new File(propLocation);
142         if (!fileLocation.exists()) {
143             logger.error("Policy file {} does not exist.", fileLocation.getAbsolutePath());
144             return null;
145         }
146         if (!fileLocation.canRead()) {
147             logger.error("Policy file {} cannot be read.", fileLocation.getAbsolutePath());
148             return null;
149         }
150         try {
151             logger.info("Loading policy file {}", fileLocation);
152             PolicyDef policyDef = DOMPolicyDef.load(fileLocation);
153             if (policyDef != null) {
154                 return policyDef;
155             }
156             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, "DOM Could not load policy");
157         } catch (DOMStructureException ex) {
158             logger.error("Error loading policy file {}: {}", fileLocation.getAbsolutePath(), ex);
159             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage());
160         }
161     }
162
163     protected PolicyDef loadPolicyUrlDef(String propLocation) {
164         InputStream is = null;
165         try {
166             URL url                     = new URL(propLocation);
167             URLConnection urlConnection = url.openConnection();
168             OnapPolicyFinderFactory.logger.info("Loading policy file {}", url);
169             is = urlConnection.getInputStream();
170             PolicyDef policyDef         = DOMPolicyDef.load(is);
171             if (policyDef != null) {
172                 return policyDef;
173             }
174         } catch (MalformedURLException ex) {
175             logger.error("Invalid URL " + propLocation + ": " + ex.getMessage(), ex);
176         } catch (IOException ex) {
177             logger.error("IOException opening URL {}: {}{}",
178                     propLocation, ex.getMessage(), ex);
179         } catch (DOMStructureException ex) {
180             logger.error("Invalid Policy " + propLocation + ": " + ex.getMessage(), ex);
181             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage());
182         } finally {
183             if (is != null) {
184                 try {
185                     is.close();
186                 } catch (IOException e) {
187                     logger.error("Exception closing InputStream for GET of url {}: {}",
188                             propLocation, e.getMessage() + "  (May be memory leak)", e);
189                 }
190             }
191         }
192         return null;
193     }
194
195     /**
196      * Finds the identifiers for all of the policies referenced by the given property name in the
197      * <code>XACMLProperties</code> and loads them using the requested loading method.
198      *
199      * @param propertyName the <code>String</code> name of the property containing the list of policy identifiers
200      * @return a <code>List</code> of <code>PolicyDef</code>s loaded from the given property name
201      */
202     protected List<PolicyDef> getPolicyDefs(String propertyName) {
203         String policyIds;
204         if (this.properties != null) {
205             policyIds = this.properties.getProperty(propertyName);
206         } else {
207             policyIds    = XACMLProperties.getProperty(propertyName);
208         }
209         if (Strings.isNullOrEmpty(policyIds)) {
210             return Collections.emptyList();
211         }
212
213         Iterable<String> policyIdArray  = Splitter.on(',').trimResults().omitEmptyStrings().split(policyIds);
214         if (policyIdArray == null) {
215             return Collections.emptyList();
216         }
217
218         List<PolicyDef> listPolicyDefs  = new ArrayList<>();
219         for (String policyId : policyIdArray) {
220             PolicyDef policyDef = this.loadPolicyDef(policyId);
221             if (policyDef != null) {
222                 listPolicyDefs.add(policyDef);
223             }
224         }
225         return listPolicyDefs;
226     }
227
228     protected synchronized void init() {
229         if (this.needsInit) {
230             logger.debug("Initializing OnapPolicyFinderFactory Properties ");
231             this.rootPolicies       = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES);
232             this.referencedPolicies = this.getPolicyDefs(XACMLProperties.PROP_REFERENCEDPOLICIES);
233             logger.debug("Root Policies: {}", this.rootPolicies.size());
234             logger.debug("Referenced Policies: {}", this.referencedPolicies.size());
235             this.needsInit  = false;
236         }
237     }
238
239     @Override
240     public PolicyFinder getPolicyFinder() throws FactoryException {
241         //
242         // Force using any properties that were passed upon construction
243         //
244         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, this.properties);
245     }
246
247     @Override
248     public PolicyFinder getPolicyFinder(Properties properties) throws FactoryException {
249         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, properties);
250     }
251
252 }