Misc XACML code coverage
[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-2020 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      * Empty private constructor. We do not want to create
72      * an instance of this without giving Properties object.
73      *
74      * @throws OnapPolicyFinderFactoryException Exception will be thrown
75      */
76     public OnapPolicyFinderFactory() throws OnapPolicyFinderFactoryException {
77         throw new OnapPolicyFinderFactoryException("Please use the constructor with Properties object.");
78     }
79
80     /**
81      * Constructor with properties passed. This will be preferred.
82      *
83      * @param properties Properties object
84      */
85     public OnapPolicyFinderFactory(Properties properties) {
86         super(properties);
87         logger.info("Constructed using properties {}", properties);
88         //
89         // Save our properties
90         //
91         this.properties = properties;
92         //
93         // Here we differ from the StdPolicyFinderFactory in that we initialize right away.
94         // We do not wait for a policy request to happen to look for and load policies.
95         //
96         this.init();
97     }
98
99     /**
100      * Loads the <code>PolicyDef</code> for the given <code>String</code> identifier by looking first
101      * for a ".file" property associated with the ID and using that to load from a <code>File</code> and
102      * looking for a ".url" property associated with the ID and using that to load from a <code>URL</code>.
103      *
104      * @param policyId the <code>String</code> identifier for the policy
105      * @return a <code>PolicyDef</code> loaded from the given identifier
106      */
107     protected PolicyDef loadPolicyDef(String policyId) {
108         String propLocation = this.properties.getProperty(policyId + PROP_FILE);
109         if (propLocation != null) {
110             //
111             // Try to load it from the file
112             //
113             PolicyDef policy = this.loadPolicyFileDef(propLocation);
114             if (policy != null) {
115                 return policy;
116             }
117         }
118
119         logger.error("No known location for Policy {}", policyId);
120         return null;
121     }
122
123     protected PolicyDef loadPolicyFileDef(String propLocation) {
124         File fileLocation   = new File(propLocation);
125         if (!fileLocation.exists()) {
126             logger.error("Policy file {} does not exist.", fileLocation.getAbsolutePath());
127             return null;
128         }
129         if (!fileLocation.canRead()) {
130             logger.error("Policy file {} cannot be read.", fileLocation.getAbsolutePath());
131             return null;
132         }
133         try {
134             logger.info("Loading policy file {}", fileLocation);
135             PolicyDef policyDef = DOMPolicyDef.load(fileLocation);
136             if (policyDef != null) {
137                 return policyDef;
138             }
139             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, "DOM Could not load policy");
140         } catch (DOMStructureException ex) {
141             logger.error("Error loading policy file {}: {}", fileLocation.getAbsolutePath(), ex);
142             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage());
143         }
144     }
145
146     /**
147      * Finds the identifiers for all of the policies referenced by the given property name in the
148      * <code>XACMLProperties</code> and loads them using the requested loading method.
149      *
150      * @param propertyName the <code>String</code> name of the property containing the list of policy identifiers
151      * @return a <code>List</code> of <code>PolicyDef</code>s loaded from the given property name
152      */
153     protected List<PolicyDef> getPolicyDefs(String propertyName) {
154         String policyIds = this.properties.getProperty(propertyName);
155         if (Strings.isNullOrEmpty(policyIds)) {
156             return Collections.emptyList();
157         }
158
159         Iterable<String> policyIdArray  = Splitter.on(',').trimResults().omitEmptyStrings().split(policyIds);
160         if (policyIdArray == null) {
161             return Collections.emptyList();
162         }
163
164         List<PolicyDef> listPolicyDefs  = new ArrayList<>();
165         for (String policyId : policyIdArray) {
166             PolicyDef policyDef = this.loadPolicyDef(policyId);
167             if (policyDef != null) {
168                 listPolicyDefs.add(policyDef);
169             }
170         }
171         return listPolicyDefs;
172     }
173
174     protected synchronized void init() {
175         if (! this.needsInit) {
176             logger.info("Does not need initialization");
177             return;
178         }
179         logger.info("Initializing OnapPolicyFinderFactory Properties ");
180
181         //
182         // Check for property that combines root policies into one policyset
183         //
184         String combiningAlgorithm = properties.getProperty(
185                 ATTPDPProperties.PROP_POLICYFINDERFACTORY_COMBINEROOTPOLICIES);
186         if (combiningAlgorithm != null) {
187             try {
188                 logger.info("Combining root policies with {}", combiningAlgorithm);
189                 //
190                 // Find the combining algorithm
191                 //
192                 CombiningAlgorithm<PolicySetChild> algorithm = CombiningAlgorithmFactory.newInstance()
193                         .getPolicyCombiningAlgorithm(new IdentifierImpl(combiningAlgorithm));
194                 //
195                 // Create our root policy
196                 //
197                 PolicySet root = new PolicySet();
198                 root.setIdentifier(new IdentifierImpl(UUID.randomUUID().toString()));
199                 root.setVersion(StdVersion.newInstance("1.0"));
200                 root.setTarget(new Target());
201                 //
202                 // Set the algorithm
203                 //
204                 root.setPolicyCombiningAlgorithm(algorithm);
205                 //
206                 // Load all our root policies
207                 //
208                 for (PolicyDef policy : this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES)) {
209                     root.addChild(policy);
210                 }
211                 //
212                 // Set this policy as the root
213                 //
214                 this.rootPolicies = new ArrayList<>();
215                 this.rootPolicies.add(root);
216             } catch (Exception e) {
217                 logger.error("Failed to load Combining Algorithm Factory", e);
218             }
219         } else {
220             logger.info("Loading root policies");
221             this.rootPolicies       = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES);
222         }
223         this.referencedPolicies = this.getPolicyDefs(XACMLProperties.PROP_REFERENCEDPOLICIES);
224         logger.info("Root Policies: {}", this.rootPolicies.size());
225         logger.info("Referenced Policies: {}", this.referencedPolicies.size());
226         //
227         // Make sure we set that we don't need initialization
228         //
229         this.needsInit  = false;
230     }
231
232     @Override
233     public PolicyFinder getPolicyFinder() throws FactoryException {
234         //
235         // Force using any properties that were passed upon construction
236         //
237         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, this.properties);
238     }
239
240     @Override
241     public PolicyFinder getPolicyFinder(Properties properties) throws FactoryException {
242         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, properties);
243     }
244
245 }