Consolidate PolicyRestAdapter setup
[policy/engine.git] / ONAP-PAP-REST / src / main / java / org / onap / policy / pap / xacml / rest / handler / DeleteHandler.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PAP-REST
4  * ================================================================================
5  * Copyright (C) 2017-2019 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.handler;
22
23 import com.att.research.xacml.api.pap.PAPException;
24 import com.att.research.xacml.api.pap.PDPPolicy;
25 import com.att.research.xacml.util.XACMLProperties;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.util.Arrays;
30 import java.util.List;
31
32 import javax.script.SimpleBindings;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35
36 import org.apache.commons.lang3.StringUtils;
37 import org.onap.policy.common.logging.OnapLoggingContext;
38 import org.onap.policy.common.logging.eelf.MessageCodes;
39 import org.onap.policy.common.logging.eelf.PolicyLogger;
40 import org.onap.policy.common.logging.flexlogger.FlexLogger;
41 import org.onap.policy.common.logging.flexlogger.Logger;
42 import org.onap.policy.pap.xacml.rest.XACMLPapServlet;
43 import org.onap.policy.pap.xacml.rest.components.PolicyDBDaoTransaction;
44 import org.onap.policy.pap.xacml.rest.elk.client.PolicyElasticSearchController;
45 import org.onap.policy.pap.xacml.rest.model.RemoveGroupPolicy;
46 import org.onap.policy.pap.xacml.rest.util.JPAUtils;
47 import org.onap.policy.rest.adapter.PolicyRestAdapter;
48 import org.onap.policy.rest.dao.CommonClassDao;
49 import org.onap.policy.rest.jpa.PolicyEntity;
50 import org.onap.policy.rest.jpa.PolicyVersion;
51 import org.onap.policy.utils.PolicyUtils;
52 import org.onap.policy.xacml.api.XACMLErrorConstants;
53 import org.onap.policy.xacml.api.pap.OnapPDPGroup;
54 import org.onap.policy.xacml.std.pap.StdPAPPolicy;
55 import org.onap.policy.xacml.std.pap.StdPDPGroup;
56 import org.springframework.beans.factory.annotation.Autowired;
57 import org.springframework.stereotype.Component;
58
59 @Component
60 public class DeleteHandler {
61
62     private static CommonClassDao commonClassDao;
63
64     @Autowired
65     public DeleteHandler(CommonClassDao commonClassDao) {
66         DeleteHandler.commonClassDao = commonClassDao;
67     }
68
69     public DeleteHandler() {
70         // Default Constructor
71     }
72
73     private OnapPDPGroup newgroup;
74     private static final Logger LOGGER = FlexLogger.getLogger(DeleteHandler.class);
75     private static final String POLICY_IN_PDP = "PolicyInPDP";
76     private static final String ERROR = "error";
77     private static final String MESSAGE = "message";
78     private static final String UNKNOWN = "unknown";
79     private static final String SUCCESS = "success";
80     private static final String OPERATION = "operation";
81     private static final String CONFIG = "Config_";
82     private static final String REGEX = "[0-9a-zA-Z._]*";
83     private static final String DELETE = "delete";
84     private static final String ACTION = "Action_";
85
86     /**
87      * Do API delete from PAP.
88      *
89      * @param request the request
90      * @param response the response
91      * @throws IOException Signals that an I/O exception has occurred.
92      */
93     public void doApiDeleteFromPap(HttpServletRequest request, HttpServletResponse response) throws IOException {
94         // get the request content into a String
95         String json = null;
96         java.util.Scanner scanner = new java.util.Scanner(request.getInputStream());
97         scanner.useDelimiter("\\A");
98         json = scanner.hasNext() ? scanner.next() : "";
99         scanner.close();
100         PolicyLogger.info("JSON request from API to Delete Policy from the PAP: " + json);
101         // convert Object sent as JSON into local object
102         StdPAPPolicy policy = PolicyUtils.jsonStringToObject(json, StdPAPPolicy.class);
103         String policyName = policy.getPolicyName();
104         boolean policyVersionDeleted = false;
105         String removeXmlExtension;
106         int currentVersion;
107         String removeVersionExtension;
108         String splitPolicyName = null;
109         String[] split = null;
110         String status = ERROR;
111         PolicyEntity policyEntity = null;
112         JPAUtils jpaUtils = null;
113
114         try {
115             jpaUtils = JPAUtils.getJPAUtilsInstance();
116         } catch (Exception e) {
117             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "doAPIDeleteFromPAP",
118                     " Could not create JPAUtils instance on the PAP");
119             response.addHeader(ERROR, "jpautils");
120             response.addHeader(OPERATION, DELETE);
121             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
122             return;
123         }
124         if (jpaUtils.dbLockdownIgnoreErrors()) {
125             PolicyLogger.warn("Policies are locked down");
126             response.addHeader(OPERATION, DELETE);
127             response.addHeader("lockdown", "true");
128             response.setStatus(HttpServletResponse.SC_ACCEPTED);
129             return;
130         }
131         String policyEntityQuery = null;
132         try {
133             if (policyName.endsWith(".xml")) {
134                 removeXmlExtension = policyName.replace(".xml", "");
135                 currentVersion =
136                         Integer.parseInt(removeXmlExtension.substring(removeXmlExtension.lastIndexOf('.') + 1));
137                 removeVersionExtension = removeXmlExtension.substring(0, removeXmlExtension.lastIndexOf('.'));
138                 boolean queryCheck = true;
139                 if ("All Versions".equalsIgnoreCase(policy.getDeleteCondition())) {
140                     if (policyName.contains(CONFIG)) {
141                         splitPolicyName = removeVersionExtension.replace(".Config_", ":Config_");
142                     } else if (policyName.contains(ACTION)) {
143                         splitPolicyName = removeVersionExtension.replace(".Action_", ":Action_");
144                     } else if (policyName.contains("Decision_")) {
145                         splitPolicyName = removeVersionExtension.replace(".Decision_", ":Decision_");
146                     }
147                     if (splitPolicyName != null) {
148                         split = splitPolicyName.split(":");
149                     } else {
150                         PolicyLogger.error(MessageCodes.ERROR_UNKNOWN
151                                 + "Failed to delete the policy. Please, provide the valid policyname.");
152                         response.addHeader(ERROR, UNKNOWN);
153                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
154                         return;
155                     }
156                     policyEntityQuery =
157                             "SELECT p FROM PolicyEntity p WHERE p.policyName LIKE :pName and p.scope=:pScope";
158                 } else if ("Current Version".equalsIgnoreCase(policy.getDeleteCondition())) {
159                     if (policyName.contains(CONFIG)) {
160                         splitPolicyName = policyName.replace(".Config_", ":Config_");
161                     } else if (policyName.contains(ACTION)) {
162                         splitPolicyName = policyName.replace(".Action_", ":Action_");
163                     } else if (policyName.contains("Decision_")) {
164                         splitPolicyName = policyName.replace(".Decision_", ":Decision_");
165                     }
166                     split = splitPolicyName.split(":");
167                     queryCheck = false;
168                     policyEntityQuery = "SELECT p FROM PolicyEntity p WHERE p.policyName=:pName and p.scope=:pScope";
169                 }
170                 SimpleBindings params = new SimpleBindings();
171                 if (queryCheck) {
172                     params.put("pName", "%" + split[1] + "%");
173                 } else {
174                     params.put("pName", split[1]);
175                 }
176
177                 params.put("pScope", split[0]);
178                 List<?> peResult = commonClassDao.getDataByQuery(policyEntityQuery, params);
179                 if (!peResult.isEmpty()) {
180                     String getPolicyVersion = "Select p from PolicyVersion p where p.policyName=:pname";
181                     SimpleBindings pvParams = new SimpleBindings();
182                     pvParams.put("pname", removeVersionExtension.replace(".", File.separator));
183                     List<?> pvResult = commonClassDao.getDataByQuery(getPolicyVersion, pvParams);
184                     PolicyVersion polVersion = (PolicyVersion) pvResult.get(0);
185                     int newVersion = 0;
186                     if ("All Versions".equalsIgnoreCase(policy.getDeleteCondition())) {
187                         boolean groupCheck = checkPolicyGroupEntity(peResult);
188                         if (!groupCheck) {
189                             for (Object peData : peResult) {
190                                 policyEntity = (PolicyEntity) peData;
191                                 status = deletePolicyEntityData(policyEntity);
192                             }
193                         } else {
194                             status = POLICY_IN_PDP;
195                         }
196                         switch (status) {
197                             case ERROR:
198                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE
199                                         + "Exception Occured while deleting the Entity from Database.");
200                                 response.addHeader(ERROR, UNKNOWN);
201                                 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
202                                 return;
203                             case POLICY_IN_PDP:
204                                 PolicyLogger.error(MessageCodes.GENERAL_WARNING
205                                         + "Policy can't be deleted, it is active in PDP Groups.");
206                                 response.addHeader(ERROR, POLICY_IN_PDP);
207                                 response.setStatus(HttpServletResponse.SC_CONFLICT);
208                                 return;
209                             default:
210                                 try {
211                                     policyVersionDeleted = true;
212                                     commonClassDao.delete(polVersion);
213                                 } catch (Exception e) {
214                                     LOGGER.error(e.getMessage(), e);
215                                     policyVersionDeleted = false;
216                                 }
217                                 break;
218                         }
219                     } else if ("Current Version".equalsIgnoreCase(policy.getDeleteCondition())) {
220                         boolean groupCheck = checkPolicyGroupEntity(peResult);
221                         if (!groupCheck) {
222                             policyEntity = (PolicyEntity) peResult.get(0);
223                             status = deletePolicyEntityData(policyEntity);
224                         } else {
225                             status = POLICY_IN_PDP;
226                         }
227
228                         if (ERROR.equals(status)) {
229                             PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE
230                                     + "Exception Occured while deleting the Entity from Database.");
231                             response.addHeader(ERROR, UNKNOWN);
232                             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
233                             return;
234                         } else if (POLICY_IN_PDP.equals(status)) {
235                             PolicyLogger.error(MessageCodes.GENERAL_WARNING
236                                     + "Policy can't be deleted, it is active in PDP Groups.");
237                             response.addHeader(ERROR, POLICY_IN_PDP);
238                             response.setStatus(HttpServletResponse.SC_CONFLICT);
239                             return;
240                         } else {
241                             if (currentVersion > 1) {
242                                 if (!peResult.isEmpty()) {
243                                     for (Object object : peResult) {
244                                         policyEntity = (PolicyEntity) object;
245                                         String policyEntityName = policyEntity.getPolicyName().replace(".xml", "");
246                                         int policyEntityVersion = Integer.parseInt(
247                                                 policyEntityName.substring(policyEntityName.lastIndexOf('.') + 1));
248                                         if (policyEntityVersion > newVersion) {
249                                             newVersion = policyEntityVersion - 1;
250                                         }
251                                     }
252                                 }
253                                 polVersion.setActiveVersion(newVersion);
254                                 polVersion.setHigherVersion(newVersion);
255                                 try {
256                                     policyVersionDeleted = true;
257                                     commonClassDao.save(polVersion);
258                                 } catch (Exception e) {
259                                     LOGGER.error(e.getMessage(), e);
260                                     policyVersionDeleted = false;
261                                 }
262                             } else {
263                                 try {
264                                     policyVersionDeleted = true;
265                                     commonClassDao.delete(polVersion);
266                                 } catch (Exception e) {
267                                     LOGGER.error(e.getMessage(), e);
268                                     policyVersionDeleted = false;
269                                 }
270                             }
271                         }
272                     }
273                 } else {
274                     PolicyLogger.error(MessageCodes.ERROR_UNKNOWN
275                             + "Failed to delete the policy for an unknown reason.  Check the file system and other logs"
276                             + " for further information.");
277                     response.addHeader(ERROR, UNKNOWN);
278                     response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
279                     return;
280                 }
281             }
282         } catch (Exception e) {
283             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "XACMLPapServlet", " ERROR");
284             response.addHeader(ERROR, "deleteDB");
285             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
286             return;
287         }
288
289         if (policyVersionDeleted) {
290             response.setStatus(HttpServletResponse.SC_OK);
291             response.addHeader("successMapKey", SUCCESS);
292             response.addHeader(OPERATION, DELETE);
293         } else {
294             PolicyLogger.error(MessageCodes.ERROR_UNKNOWN
295                     + "Failed to delete the policy for an unknown reason.  Check the file system and other logs for "
296                     + "further information.");
297             response.addHeader(ERROR, UNKNOWN);
298             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
299         }
300     }
301
302     /**
303      * Delete policy entity data.
304      *
305      * @param policyEntity the policy entity
306      * @return the string
307      */
308     public static String deletePolicyEntityData(PolicyEntity policyEntity) {
309         PolicyElasticSearchController controller = new PolicyElasticSearchController();
310         PolicyRestAdapter policyData = new PolicyRestAdapter();
311         String policyName = policyEntity.getPolicyName();
312         try {
313             if (policyName.contains("CONFIG") || policyName.contains("Decision_MS_")) {
314                 commonClassDao.delete(policyEntity.getConfigurationData());
315             } else if (policyName.contains(ACTION)) {
316                 commonClassDao.delete(policyEntity.getActionBodyEntity());
317             }
318             String searchPolicyName = policyEntity.getScope() + "." + policyEntity.getPolicyName();
319             policyData.setNewFileName(searchPolicyName);
320             controller.deleteElk(policyData);
321             commonClassDao.delete(policyEntity);
322         } catch (Exception e) {
323             LOGGER.error(e.getMessage(), e);
324             return ERROR;
325         }
326         return SUCCESS;
327     }
328
329     /**
330      * Check policy group entity.
331      *
332      * @param peResult the pe result
333      * @return true, if successful
334      */
335     public static boolean checkPolicyGroupEntity(List<?> peResult) {
336         String groupEntityquery = "from PolicyGroupEntity where policyid = :policyEntityId";
337         for (Object peData : peResult) {
338             PolicyEntity policyEntity = (PolicyEntity) peData;
339             SimpleBindings geParams = new SimpleBindings();
340             geParams.put("policyEntityId", policyEntity.getPolicyId());
341             List<Object> groupobject = commonClassDao.getDataByQuery(groupEntityquery, geParams);
342             if (!groupobject.isEmpty()) {
343                 return true;
344             }
345         }
346         return false;
347     }
348
349     /**
350      * Do API delete from PDP.
351      *
352      * @param request the request
353      * @param response the response
354      * @param loggingContext the logging context
355      * @throws IOException Signals that an I/O exception has occurred.
356      */
357     public void doApiDeleteFromPdp(HttpServletRequest request, HttpServletResponse response,
358             OnapLoggingContext loggingContext) throws IOException {
359
360         String groupId = request.getParameter("groupId");
361
362         if (groupId != null && !groupId.matches(REGEX)) {
363             response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
364             response.addHeader(ERROR, ERROR);
365             response.addHeader(MESSAGE, "Group Id is not valid");
366             return;
367         }
368         String requestId = request.getHeader("X-ECOMP-RequestID");
369         String polName = request.getParameter("policyName");
370         LOGGER.info("JSON request from API to Delete Policy from the PDP - " + polName + " -RequestId - " + requestId);
371
372         // for PUT operations the group may or may not need to exist before the operation can be
373         // done
374         OnapPDPGroup group = null;
375         try {
376             group = XACMLPapServlet.getPAPEngine().getGroup(groupId);
377         } catch (PAPException e) {
378             LOGGER.error("Exception occured While PUT operation is performing for PDP Group" + " -  RequestId - "
379                     + requestId + e);
380         }
381         if (group == null) {
382             String message = "Unknown groupId '" + groupId + "'.";
383             LOGGER.error(MessageCodes.ERROR_DATA_ISSUE + " - RequestId -  " + requestId + " - " + message);
384             loggingContext.transactionEnded();
385             PolicyLogger.audit("Transaction Failed - See Error.log");
386             response.addHeader(ERROR, "UnknownGroup");
387             response.addHeader(MESSAGE, message);
388             response.setStatus(HttpServletResponse.SC_NOT_FOUND);
389             return;
390         }
391         loggingContext.setServiceName("API:PAP.deletPolicyFromPDPGroup");
392         RemoveGroupPolicy removePolicy = new RemoveGroupPolicy((StdPDPGroup) group);
393         removePolicy.prepareToRemove();
394         List<String> policyIdList = Arrays.asList(polName.split(","));
395         for (String policyName : policyIdList) {
396             if (!policyName.endsWith("xml")) {
397                 String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid policyName... "
398                         + "policyName must be the full name of the file to be deleted including version and extension";
399                 LOGGER.error(message + "   - RequestId - " + requestId);
400                 response.addHeader(ERROR, message);
401                 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
402                 return;
403             }
404             PDPPolicy policy = group.getPolicy(policyName);
405             if (policy == null) {
406                 String message =
407                         XACMLErrorConstants.ERROR_DATA_ISSUE + "Policy does not exist on the PDP - " + policyName;
408                 LOGGER.error(message + " - RequestId   - " + requestId);
409                 response.addHeader(ERROR, message);
410                 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
411                 return;
412             }
413             if (StringUtils.indexOfAny(policy.getId(), "Config_MS_", "BRMS_Param") >= 0) {
414                 preSafetyCheck(policy);
415             }
416             LOGGER.info("Preparing to remove policy from group: " + group.getId() + "- RequestId - " + requestId);
417             removePolicy.removePolicy(policy);
418         }
419         OnapPDPGroup updatedGroup = removePolicy.getUpdatedObject();
420         String userId = request.getParameter("userId");
421         String responseString = deletePolicyFromPdpGroup(updatedGroup, loggingContext, userId);
422
423         switch (responseString) {
424             case SUCCESS:
425                 loggingContext.transactionEnded();
426                 LOGGER.info("Policy successfully removed from PDP - " + polName + " -   RequestId - " + requestId);
427                 PolicyLogger.audit("Policy successfully deleted!");
428                 response.setStatus(HttpServletResponse.SC_OK);
429                 response.addHeader("successMapKey", SUCCESS);
430                 response.addHeader(OPERATION, DELETE);
431                 break;
432             case "No Group":
433                 String message = XACMLErrorConstants.ERROR_DATA_ISSUE + "Group update had bad input.";
434                 LOGGER.error(message + " - RequestId - " + requestId);
435                 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
436                 response.addHeader(ERROR, "groupUpdate");
437                 response.addHeader(MESSAGE, message);
438                 break;
439             case "DB Error":
440                 LOGGER.error(MessageCodes.ERROR_PROCESS_FLOW + " Error while updating group in the database"
441                         + " - RequestId - " + requestId);
442                 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
443                 response.addHeader(ERROR, "deleteDB");
444                 break;
445             default:
446                 LOGGER.error(MessageCodes.ERROR_UNKNOWN
447                         + " Failed to delete the policy for an unknown reason.  Check the file system and other logs "
448                         + "for " + "further information.");
449                 response.addHeader(ERROR, UNKNOWN);
450                 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
451                 break;
452         }
453     }
454
455     private String deletePolicyFromPdpGroup(OnapPDPGroup group, OnapLoggingContext loggingContext, String userId) {
456         PolicyDBDaoTransaction acPutTransaction = XACMLPapServlet.getDbDaoTransaction();
457         String response = null;
458         loggingContext.setServiceName("API:PAP.DeleteHandler");
459         OnapPDPGroup existingGroup = null;
460         try {
461             existingGroup = XACMLPapServlet.getPAPEngine().getGroup(group.getId());
462         } catch (PAPException e1) {
463             PolicyLogger.error("Exception occured While Deleting Policy From PDP Group" + e1);
464         }
465         if (!(group instanceof StdPDPGroup) || existingGroup == null
466                 || !(group.getId().equals(existingGroup.getId()))) {
467             String existingId = null;
468             if (existingGroup != null) {
469                 existingId = existingGroup.getId();
470             }
471             PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " Group update had bad input. id=" + existingId
472                     + " objectFromJSON=" + group);
473             loggingContext.transactionEnded();
474             PolicyLogger.audit("Transaction Failed - See Error.log");
475             response = "No Group";
476             return response;
477         }
478         // The Path on the PAP side is not carried on the RESTful interface with the AC
479         // (because it is local to the PAP)
480         // so we need to fill that in before submitting the group for update
481         ((StdPDPGroup) group).setDirectory(((StdPDPGroup) existingGroup).getDirectory());
482         try {
483             acPutTransaction.updateGroup(group, "XACMLPapServlet.doDelete", userId);
484         } catch (Exception e) {
485             PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet",
486                     " Error while updating group in the database: " + "group=" + existingGroup.getId());
487             response = "DB Error";
488             return response;
489         }
490         try {
491             XACMLPapServlet.getPAPEngine().updateGroup(group);
492         } catch (PAPException e) {
493             PolicyLogger.error("Exception occured While Updating PDP Groups" + e);
494             response = "error in updateGroup method";
495         }
496         PolicyLogger.debug("Group '" + group.getId() + "' updated");
497         acPutTransaction.commitTransaction();
498         // Group changed, which might include changing the policies
499         try {
500             newgroup = existingGroup;
501         } catch (Exception e) {
502             PolicyLogger.error("Exception occured in Group Change Method" + e);
503             response = "error in groupChanged method";
504         }
505         if (response == null) {
506             response = SUCCESS;
507             loggingContext.transactionEnded();
508             PolicyLogger.audit("Policy successfully deleted!");
509         }
510         loggingContext.transactionEnded();
511         PolicyLogger.audit("Transaction Ended");
512         return response;
513     }
514
515     public OnapPDPGroup getDeletedGroup() {
516         return newgroup;
517     }
518
519     public boolean preSafetyCheck(PDPPolicy policy) {
520         return true;
521     }
522
523     /**
524      * Gets the single instance of DeleteHandler.
525      *
526      * @return single instance of DeleteHandler
527      */
528     public static DeleteHandler getInstance() {
529         try {
530             Class<?> deleteHandler = Class
531                     .forName(XACMLProperties.getProperty("deletePolicy.impl.className", DeleteHandler.class.getName()));
532             return (DeleteHandler) deleteHandler.newInstance();
533         } catch (Exception e) {
534             LOGGER.error(e.getMessage(), e);
535         }
536         return null;
537     }
538
539 }