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