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