Merge "Adding Junits for policy engine"
[policy/engine.git] / ONAP-PAP-REST / src / main / java / org / onap / policy / pap / xacml / rest / components / Policy.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PAP-REST
4  * ================================================================================
5  * Copyright (C) 2017 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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pap.xacml.rest.components;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.net.URI;
26 import java.net.URISyntaxException;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.util.HashMap;
31 import java.util.Map;
32
33 import org.apache.commons.io.FilenameUtils;
34 import org.onap.policy.common.logging.eelf.MessageCodes;
35 import org.onap.policy.common.logging.eelf.PolicyLogger;
36 import org.onap.policy.common.logging.flexlogger.FlexLogger;
37 import org.onap.policy.common.logging.flexlogger.Logger;
38 import org.onap.policy.rest.XACMLRestProperties;
39 import org.onap.policy.rest.adapter.PolicyRestAdapter;
40 import org.onap.policy.xacml.util.XACMLPolicyWriter;
41
42 import com.att.research.xacml.api.pap.PAPException;
43 import com.att.research.xacml.std.IdentifierImpl;
44 import com.att.research.xacml.util.XACMLProperties;
45 import com.att.research.xacmlatt.pdp.policy.PolicyDef;
46 import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef;
47
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
52
53 public abstract class Policy {
54         
55         private static final Logger LOGGER      = FlexLogger.getLogger(Policy.class);
56         
57
58         /**
59          * Common Fields
60          */
61         public static final String GET_INT_TYPE = "Integer";
62         public static final String GET_STRING_TYPE = "String";
63
64         public static final String ONAPID = "ONAPName";
65         public static final String CONFIGID = "ConfigName";
66         public static final String CLOSEDLOOPID = "ServiceType";
67
68         public static final String CONFIG_POLICY = "Config";
69         public static final String ACTION_POLICY = "Action";
70         public static final String DECISION_POLICY = "Decision";
71
72         protected String policyName = null;
73
74         protected boolean isValidForm = true;
75
76         private Path finalPolicyPath = null;
77
78         private boolean preparedToSave = false;
79
80         private boolean policyExists = false;
81
82         public Path getFinalPolicyPath() {
83                 return finalPolicyPath;
84         }
85
86         public void setFinalPolicyPath(Path finalPolicyPath) {
87                 this.finalPolicyPath = finalPolicyPath;
88         }
89
90         // Constants Used in XML Creation
91         public static final String CATEGORY_RECIPIENT_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject";
92         public static final String CATEGORY_RESOURCE = "urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
93         public static final String CATEGORY_ACTION = "urn:oasis:names:tc:xacml:3.0:attribute-category:action";
94         public static final String CATEGORY_ACCESS_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
95         public static final String ACTION_ID = "urn:oasis:names:tc:xacml:1.0:action:action-id";
96         public static final String SUBJECT_ID = "urn:oasis:names:tc:xacml:1.0:subject:subject-id";
97         public static final String RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
98         public static final String FUNTION_INTEGER_ONE_AND_ONLY = "urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only";
99         public static final String FUNCTION_STRING_ONE_AND_ONLY = "urn:oasis:names:tc:xacml:1.0:function:string-one-and-only";
100         public static final String FUNCTION_BOOLEAN_ONE_AND_ONLY = "urn:oasis:names:tc:xacml:1.0:function:boolean-one-and-only";
101         public static final String FUNCTION_STRING_EQUAL = "urn:oasis:names:tc:xacml:1.0:function:string-equal";
102         public static final String FUNCTION_STRING_REGEX_MATCH = "org.onap.function.regex-match";
103         public static final String FUNCTION_STRING_REGEXP_MATCH = "urn:oasis:names:tc:xacml:1.0:function:string-regexp-match";
104         public static final String FUNCTION_STRING_EQUAL_IGNORE = "urn:oasis:names:tc:xacml:3.0:function:string-equal-ignore-case";
105         public static final String INTEGER_DATATYPE = "http://www.w3.org/2001/XMLSchema#integer";
106         public static final String BOOLEAN_DATATYPE = "http://www.w3.org/2001/XMLSchema#boolean";
107         public static final String STRING_DATATYPE = "http://www.w3.org/2001/XMLSchema#string";
108         public static final String URI_DATATYPE = "http://www.w3.org/2001/XMLSchema#anyURI";
109         public static final String RULE_VARIABLE = "var:";
110         public static final String EMPTY_STRING = "";
111         private static final String String = null;
112
113         protected static String CONFIG_HOME = null;
114         protected static String ACTION_HOME = null;
115         protected static String CONFIG_URL = null;
116
117         protected Map<String, String> performer = new HashMap<>();
118
119         private static String actionHome = null;
120         private static String configHome = null;
121
122         public PolicyRestAdapter policyAdapter = null;
123         String ruleID = "";
124
125         public Policy() {
126                 CONFIG_HOME = getConfigHome();
127                 ACTION_HOME = getActionHome();
128                 CONFIG_URL = "$URL";
129                 performer.put("PDP", "PDPAction");
130                 performer.put("PEP", "PEPAction");
131         }
132
133         //Each policy type seems to either use policyData or data field policy adapter when
134         //getting the xml to save the policy. Instead of keep this hardcoded in the save method,
135         //this method makes it usable outside.
136         /**
137          * Return the data field of the PolicyAdapter that will be used when saving this policy
138          * with the savePolicies method.
139          * @return Either the PolicyAdapter.getData() or PolicyAdapter.getPolicyData()
140          */
141         public abstract Object getCorrectPolicyDataObject();
142         public abstract Map<String, String>  savePolicies() throws PAPException;
143
144         //This is the method for preparing the policy for saving.  We have broken it out
145         //separately because the fully configured policy is used for multiple things
146         public abstract boolean prepareToSave() throws PAPException;
147
148
149         // create match for onap and config name
150         protected MatchType createMatch(String key, String value) {
151                 MatchType match = new MatchType();
152
153                 AttributeValueType attributeValue = new AttributeValueType();
154                 attributeValue.setDataType(STRING_DATATYPE);
155                 attributeValue.getContent().add(value);
156                 match.setAttributeValue(attributeValue);
157                 AttributeDesignatorType attributeDesignator = new AttributeDesignatorType();
158                 URI uri = null;
159                 try {
160                         uri = new URI(key);
161                 } catch (URISyntaxException e) {
162                         LOGGER.error("Exception Occured"+e);
163                 }
164                 attributeDesignator.setCategory(CATEGORY_ACCESS_SUBJECT);
165                 attributeDesignator.setDataType(STRING_DATATYPE);
166                 attributeDesignator.setAttributeId(new IdentifierImpl(uri).stringValue());
167                 match.setAttributeDesignator(attributeDesignator);
168                 match.setMatchId(FUNCTION_STRING_REGEX_MATCH);
169                 return match;
170         }
171
172         // Creating the match for dynamically added components.
173         protected MatchType createDynamicMatch(String key, String value) {
174                 MatchType dynamicMatch = new MatchType();
175                 AttributeValueType dynamicAttributeValue = new AttributeValueType();
176                 String dataType = null;
177                 dataType = STRING_DATATYPE;
178                 dynamicAttributeValue.setDataType(dataType);
179                 dynamicAttributeValue.getContent().add(value);
180                 dynamicMatch.setAttributeValue(dynamicAttributeValue);
181
182                 AttributeDesignatorType dynamicAttributeDesignator = new AttributeDesignatorType();
183
184                 URI dynamicURI = null;
185                 try {
186                         dynamicURI = new URI(key);
187                 } catch (URISyntaxException e) {
188                         LOGGER.error("Exception Occured"+e);// log msg
189                 }
190                 dynamicAttributeDesignator.setCategory(CATEGORY_RESOURCE);
191                 dynamicAttributeDesignator.setDataType(dataType);
192                 dynamicAttributeDesignator.setAttributeId(new IdentifierImpl(dynamicURI).stringValue());
193                 dynamicMatch.setAttributeDesignator(dynamicAttributeDesignator);
194                 dynamicMatch.setMatchId(FUNCTION_STRING_REGEX_MATCH);
195
196                 return dynamicMatch;
197         }
198
199         //  the Policy Name as Unique One throws error
200         @SuppressWarnings("static-access")
201         protected Path getNextFilename(Path parent, String policyType, String polcyFileName, Integer version) {
202                 policyType = FilenameUtils.removeExtension(policyType);
203                 polcyFileName = FilenameUtils.removeExtension(polcyFileName);
204                 Path newFile = null;
205                 String policyDir = EMPTY_STRING;
206                 String absolutePath = parent.toString();
207                 if (absolutePath != null && !absolutePath.equals(EMPTY_STRING)) {
208                         policyDir = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.length());
209                         if (policyDir == null || policyDir.equals(EMPTY_STRING)) {
210                                 policyDir = absolutePath.substring(absolutePath.lastIndexOf("/") + 1, absolutePath.length());
211                         }
212                 }
213
214                 String fileName = "default";
215                 if (policyDir != null && !policyDir.equals(EMPTY_STRING)) {
216                         fileName = policyType + "_" + String.format(polcyFileName) + "." + version + ".xml";
217                 } 
218                 if (fileName != null) {
219                         newFile = Paths.get(parent.toString(), fileName);
220                 }
221                 if (Files.notExists(newFile)) {
222                         return newFile;
223                 }
224                 return null;
225         }
226
227         protected Path getNextLoopFilename(Path parentPath, String policyType, String policyConfigType, String policyFileName, Integer version) {
228                 policyType = FilenameUtils.removeExtension(policyType);
229                 policyConfigType = FilenameUtils.removeExtension(policyConfigType);
230                 policyFileName = FilenameUtils.removeExtension(policyFileName);
231                 Path newFile = null;
232                 String policyDir = EMPTY_STRING;
233                 String absolutePath = parentPath.toString();
234                 if (absolutePath != null && !absolutePath.equals(EMPTY_STRING)) {
235                         policyDir = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.length());
236                         if (policyDir == null || policyDir.equals(EMPTY_STRING)) {
237                                 policyDir = absolutePath.substring(absolutePath.lastIndexOf("/") + 1, absolutePath.length());
238                         }
239                 }
240
241                 String fileName = "default";
242                 if (policyDir != null && !policyDir.equals(EMPTY_STRING)) {
243                         if(policyConfigType.equals("ClosedLoop_PM")){
244                                 fileName = policyType + "_" + "PM" + "_" +java.lang.String.format(policyFileName) + "." +version +".xml";
245                         }else if(policyConfigType.equals("ClosedLoop_Fault")){
246                                 fileName = policyType + "_" + "Fault" + "_" +java.lang.String.format(policyFileName) +  "." + version + ".xml";
247                         }else if(policyConfigType.equals("Micro Service")){
248                                 fileName = policyType + "_" + "MS" + "_" + java.lang.String.format(policyFileName) + "." + version + ".xml";
249                         }
250                 } 
251                 if (fileName != null) {
252                         newFile = Paths.get(parentPath.toString(), fileName);
253                 }
254                 if (Files.notExists(newFile)) {
255                         return newFile;
256                 }
257                 return null;
258         }
259
260
261         //create policy once all the validations are completed
262         protected Map<String, String> createPolicy(final Path policyPath, final Object policyData) {
263                 Map<String, String> success = new HashMap<>(); 
264                 //
265                 // Is the root a PolicySet or Policy?
266                 //
267
268                 if (policyData instanceof PolicyType) {
269                         //
270                         // Write it out
271                         //
272                         //Does not need to be XACMLPolicyWriterWithPapNotify since it is already in the PAP
273                         //and this transaction is intercepted up stream.
274                         InputStream inputStream = null;
275                         try {
276                                 inputStream = XACMLPolicyWriter.getXmlAsInputStream((PolicyType) policyData);
277                                 PolicyDef policyDef = DOMPolicyDef.load(inputStream);
278                                 if (policyDef == null) {
279                                         success.put("validation", "PolicyDef Validation Failed");
280                                 }else{
281                                         success.put("success", "success");
282                                 }
283                         } catch (Exception e) {
284                                 LOGGER.error("PolicyDef Validation failed"+e);
285                                 success.put("error", "Validation Failed");
286                         }finally{
287                                 try {
288                                         if(inputStream != null)
289                                                 inputStream.close();
290                                 } catch (IOException e) {
291                                         LOGGER.error("Exception Occured while closing the input stream"+e);
292                                 }
293                         }
294                 } else {
295                         PolicyLogger.error("Unknown data type sent back.");
296                         return success;
297                 }
298                 return success;
299         }
300
301         public static String getConfigHome(){
302                 try {
303                         loadWebapps();
304                 } catch (Exception e) {
305                         LOGGER.debug(e);
306                         return null;
307                 }
308                 return configHome;
309         }
310
311         public static String getActionHome(){
312                 try {
313                         loadWebapps();
314                 } catch (Exception e) {
315                         LOGGER.debug(e);
316                         return null;
317                 }
318                 return actionHome;
319         }
320
321         private static void loadWebapps() throws PAPException{
322                 if(actionHome == null || configHome == null){
323                         Path webappsPath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS));
324                         //Sanity Check
325                         if (webappsPath == null) {
326                                 PolicyLogger.error("Invalid Webapps Path Location property : " + XACMLRestProperties.PROP_PAP_WEBAPPS);
327                                 throw new PAPException("Invalid Webapps Path Location property : " + XACMLRestProperties.PROP_PAP_WEBAPPS);
328                         }
329                         Path webappsPathConfig;
330                         Path webappsPathAction;
331                         if(webappsPath.toString().contains("\\")){
332                                 webappsPathConfig = Paths.get(webappsPath.toString()+"\\Config");
333                                 webappsPathAction = Paths.get(webappsPath.toString()+"\\Action");
334                         }else{
335                                 webappsPathConfig = Paths.get(webappsPath.toString()+"/Config");
336                                 webappsPathAction = Paths.get(webappsPath.toString()+"/Action");
337                         }
338                         if(!webappsPathConfig.toFile().exists()){
339                                 try {
340                                         Files.createDirectories(webappsPathConfig);
341                                 } catch (IOException e) {
342                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Policy", "Failed to create config directory");
343                                 }
344                         }
345                         if(!webappsPathAction.toFile().exists()){
346                                 try {
347                                         Files.createDirectories(webappsPathAction);
348                                 } catch (IOException e) {
349                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "Policy", "Failed to create config directory");
350                                 }
351                         }
352                         actionHome = webappsPathAction.toString();
353                         configHome = webappsPathConfig.toString();
354                 }
355         }
356         
357         public boolean validateConfigForm() {
358                 return true;
359         }
360
361         /**
362          * @return the preparedToSave
363          */
364         public boolean isPreparedToSave() {
365                 return preparedToSave;
366         }
367
368         /**
369          * @param preparedToSave the preparedToSave to set
370          */
371         protected void setPreparedToSave(boolean preparedToSave) {
372                 this.preparedToSave = preparedToSave;
373         }
374
375         public boolean isPolicyExists() {
376                 return policyExists;
377         }
378
379         public void setPolicyExists(boolean policyExists) {
380                 this.policyExists = policyExists;
381         }
382
383
384 }