16340e5fec360b5e4beae22a1ecda52692df038a
[policy/engine.git] / ONAP-PAP-REST / src / main / java / org / onap / policy / pap / xacml / rest / ConsoleAndApiService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PAP-REST
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pap.xacml.rest;
23
24 import com.att.research.xacml.api.pap.PAPException;
25 import com.fasterxml.jackson.databind.ObjectMapper;
26
27 import java.io.IOException;
28 import java.io.UnsupportedEncodingException;
29 import java.net.URLDecoder;
30 import java.nio.file.Files;
31 import java.nio.file.Paths;
32 import java.util.Arrays;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Scanner;
36 import java.util.Set;
37
38 import javax.servlet.ServletException;
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpServletResponse;
41
42 import org.onap.policy.common.logging.OnapLoggingContext;
43 import org.onap.policy.common.logging.eelf.MessageCodes;
44 import org.onap.policy.common.logging.eelf.PolicyLogger;
45 import org.onap.policy.common.logging.flexlogger.FlexLogger;
46 import org.onap.policy.common.logging.flexlogger.Logger;
47 import org.onap.policy.pap.xacml.rest.components.PolicyDbDao;
48 import org.onap.policy.pap.xacml.rest.components.PolicyDbDaoTransaction;
49 import org.onap.policy.pap.xacml.rest.handler.PushPolicyHandler;
50 import org.onap.policy.xacml.api.XACMLErrorConstants;
51 import org.onap.policy.xacml.api.pap.OnapPDP;
52 import org.onap.policy.xacml.api.pap.OnapPDPGroup;
53 import org.onap.policy.xacml.api.pap.PAPPolicyEngine;
54 import org.onap.policy.xacml.std.pap.StdPDP;
55 import org.onap.policy.xacml.std.pap.StdPDPGroup;
56 import org.onap.policy.xacml.std.pap.StdPDPPolicy;
57
58 public class ConsoleAndApiService {
59
60     private static final String SPACE_UNIMPLEMENTED = " UNIMPLEMENTED";
61     private static final String XACMLPAPSERVLET_DO_AC_PUT_COMMIT_TRANS = "XACMLPapServlet doACPut commitTransaction";
62     private static final String UNIMPLEMENTED = "UNIMPLEMENTED";
63     private static final String APPLICATION_JSON = "application/json";
64     private static final String CONTENT_TYPE = "content-type";
65     private static final String TO_GROUP = ",to group=";
66     private static final String PDP_ID = "pdpId";
67     private static final String XACML_PAP_SERVLET_DO_AC_PUT = "XACMLPapServlet.doACPut";
68     private static final String UNKNOWN_GROUP_ID = "Unknown groupId '";
69     private static final Logger LOGGER = FlexLogger.getLogger(ConsoleAndApiService.class);
70     private static final Logger auditLogger = FlexLogger.getLogger("auditLogger");
71     private static final String ADD_GROUP_ERROR = "addGroupError";
72     private static final String REGEX = "[0-9a-zA-Z._, ]*";
73     private static final String TRANSACTIONFAILED = "Transaction Failed - See Error.log";
74     private static final String PAPSERVLETDOACPOST = "XACMLPapServlet.doACPost";
75     private static final String ACPOSTCOMMITTRANS = "XACMLPapServlet doACPost commitTransaction";
76     private static final String XACMLPAPSERVLET = "XACMLPapServlet";
77     private static final String SUCCESS = "Success";
78     private static final String ERROR = "error";
79     private static final String MESSAGE = "message";
80     private static final String POLICYID = "policyId";
81     private static final String TRANSENDED = "Transaction Ended Successfully";
82
83     /**
84      * Requests from the Admin Console for operations not on single specific objects.
85      *
86      * @param request Servlet request
87      * @param response Servlet response
88      * @param groupId the group id
89      * @param loggingContext the logging context
90      * @param papEngine the pap engine
91      * @throws ServletException the servlet exception
92      * @throws IOException Signals that an I/O exception has occurred.
93      */
94     public void doAcPost(HttpServletRequest request, HttpServletResponse response, String groupId,
95             OnapLoggingContext loggingContext, PAPPolicyEngine papEngine) throws IOException {
96         PolicyDbDaoTransaction doAcPostTransaction = null;
97         try {
98             String groupName = request.getParameter("groupName");
99             String groupDescription = request.getParameter("groupDescription");
100             String apiflag = request.getParameter("apiflag");
101             String userId = request.getParameter("userId");
102             if (groupName != null && groupDescription != null) {
103                 // Args: group=<groupId> groupName=<name>
104                 // groupDescription=<description> <= create a new group
105                 loggingContext.setServiceName("AC:PAP.createGroup");
106                 String unescapedName = null;
107                 String unescapedDescription = null;
108                 try {
109                     unescapedName = URLDecoder.decode(groupName, "UTF-8");
110                     unescapedDescription = URLDecoder.decode(groupDescription, "UTF-8");
111                 } catch (UnsupportedEncodingException e) {
112                     LOGGER.error(e);
113                 }
114                 PolicyDbDaoTransaction newGroupTransaction = XACMLPapServlet.getPolicyDbDao().getNewTransaction();
115                 try {
116                     newGroupTransaction.createGroup(PolicyDbDao.createNewPdpGroupId(unescapedName), unescapedName,
117                             unescapedDescription, PAPSERVLETDOACPOST);
118                     papEngine.newGroup(unescapedName, unescapedDescription);
119                     loggingContext.metricStarted();
120                     newGroupTransaction.commitTransaction();
121                     loggingContext.metricEnded();
122                     PolicyLogger.metrics(ACPOSTCOMMITTRANS);
123                 } catch (Exception e) {
124                     newGroupTransaction.rollbackTransaction();
125                     PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET,
126                             " Unable to create new group");
127                     loggingContext.transactionEnded();
128                     PolicyLogger.audit(TRANSACTIONFAILED);
129                     setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
130                             "Unable to create new group '" + groupId + "'");
131                     return;
132                 }
133                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
134                 if (LOGGER.isDebugEnabled()) {
135                     LOGGER.debug("New Group '" + groupId + "' created");
136                 }
137                 auditLogger.info(SUCCESS);
138                 PolicyLogger.audit(TRANSENDED);
139                 return;
140             }
141             // for all remaining POST operations the group must exist before the
142             // operation can be done
143             OnapPDPGroup group = null;
144             try {
145                 group = papEngine.getGroup(groupId);
146             } catch (PAPException e) {
147                 LOGGER.error(e);
148             }
149             if (group == null) {
150                 String message = UNKNOWN_GROUP_ID + groupId + "'";
151                 // for fixing Header Manipulation of Fortify issue
152                 if (!message.matches(REGEX)) {
153                     response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
154                     response.addHeader(ERROR, ADD_GROUP_ERROR);
155                     response.addHeader(MESSAGE, "GroupId Id is not valid");
156                     return;
157                 }
158                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
159                 loggingContext.transactionEnded();
160                 PolicyLogger.audit(TRANSACTIONFAILED);
161                 if (apiflag != null) {
162                     response.addHeader(ERROR, "unknownGroupId");
163                     response.addHeader("operation", "push");
164                     response.addHeader(MESSAGE, message);
165                     response.setStatus(HttpServletResponse.SC_NOT_FOUND);
166                 } else {
167                     setResponseError(response, HttpServletResponse.SC_NOT_FOUND, message);
168                 }
169                 return;
170             }
171
172             // If the request contains a policyId then we know we are pushing
173             // the policy to PDP
174             if (request.getParameter(POLICYID) != null) {
175                 String policyName = request.getParameter(POLICYID);
176                 List<String> policyIdList = Arrays.asList(policyName.split(","));
177
178                 loggingContext.setServiceName("PolicyEngineAPI:PAP.postPolicy");
179                 LOGGER.info("PushPolicy Request - " + policyName + ", UserId - " + userId);
180
181                 StdPDPGroup updatedGroup = null;
182                 StdPDPPolicy policyForSafetyCheck = new StdPDPPolicy();
183                 for (String policyId : policyIdList) {
184                     PolicyDbDaoTransaction addPolicyToGroupTransaction =
185                             XACMLPapServlet.getPolicyDbDao().getNewTransaction();
186                     try {
187                         // Copying the policy to the file system and updating groups
188                         // in database
189                         LOGGER.info("PapServlet: calling PolicyDBDao.addPolicyToGroup()");
190                         updatedGroup = addPolicyToGroupTransaction.addPolicyToGroup(group.getId(), policyId,
191                                 PAPSERVLETDOACPOST, userId);
192                         loggingContext.metricStarted();
193                         addPolicyToGroupTransaction.commitTransaction();
194                         loggingContext.metricEnded();
195                         PolicyLogger.metrics(ACPOSTCOMMITTRANS);
196                         LOGGER.info("PapServlet: addPolicyToGroup() succeeded, transaction was committed");
197
198                         if (policyId.contains("Config_MS_") || policyId.contains("BRMS_Param")) {
199                             PushPolicyHandler pushPolicyHandler = PushPolicyHandler.getInstance();
200                             policyForSafetyCheck.setId(policyId);
201                             if (pushPolicyHandler.preSafetyCheck(policyForSafetyCheck,
202                                     XACMLPapServlet.getConfigHome())) {
203                                 LOGGER.debug("Precheck Successful.");
204                             }
205                         }
206
207                         // delete temporary policy file from the bin directory
208                         Files.deleteIfExists(Paths.get(policyId));
209
210                     } catch (Exception e) {
211                         addPolicyToGroupTransaction.rollbackTransaction();
212                         String message = "Policy '" + policyName + "' not copied to group '" + groupId + "': " + e;
213                         // for fixing Header Manipulation of Fortify issue
214                         if (!message.matches(REGEX)) {
215                             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
216                             response.addHeader(ERROR, ADD_GROUP_ERROR);
217                             response.addHeader(MESSAGE, "Policy Id is not valid");
218                             return;
219                         }
220                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW + " " + message);
221                         loggingContext.transactionEnded();
222                         PolicyLogger.audit(TRANSACTIONFAILED);
223                         if (apiflag != null) {
224                             response.addHeader(ERROR, "policyCopyError");
225                             response.addHeader(MESSAGE, message);
226                             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
227                         } else {
228                             setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
229                         }
230                         return;
231                     }
232                 }
233
234                 /*
235                  * If request comes from the API we need to run the PolicyDBDao updateGroup() to notify other paps of
236                  * the change. The GUI does this from the POLICY-SDK-APP code.
237                  */
238
239                 // Get new transaction to perform updateGroup()
240                 PolicyDbDaoTransaction acPutTransaction = XACMLPapServlet.getPolicyDbDao().getNewTransaction();
241                 try {
242                     // Assume that this is an update of an existing PDP
243                     // Group
244                     loggingContext.setServiceName("PolicyEngineAPI:PAP.updateGroup");
245                     try {
246                         acPutTransaction.updateGroup(updatedGroup, XACML_PAP_SERVLET_DO_AC_PUT, userId);
247                     } catch (Exception e) {
248                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET,
249                                 " Error occurred when notifying PAPs of a group change: " + e);
250                         throw new PAPException(e.getMessage());
251                     }
252
253                     LOGGER.info("Calling updatGroup() with new group");
254                     papEngine.updateGroup(updatedGroup);
255
256                     LOGGER.info("Group - '" + updatedGroup.getId() + "' updated");
257
258                     // Commit transaction to send notification to other PAPs
259                     loggingContext.metricStarted();
260                     acPutTransaction.commitTransaction();
261                     loggingContext.metricEnded();
262                     PolicyLogger.metrics("XACMLPapServlet updateGroupsFromAPI commitTransaction");
263                     // Group changed to send notification to PDPs, which
264                     // might include changing the policies
265                     getPapInstance().groupChanged(updatedGroup, loggingContext);
266                     loggingContext.transactionEnded();
267                     LOGGER.info(SUCCESS);
268                 } catch (Exception e) {
269                     acPutTransaction.rollbackTransaction();
270                     PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET, " API PUT exception");
271                     loggingContext.transactionEnded();
272                     PolicyLogger.audit(TRANSACTIONFAILED);
273                     String message = XACMLErrorConstants.ERROR_PROCESS_FLOW
274                             + "Exception occurred when updating the group from API.";
275                     LOGGER.error(message);
276                     setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
277                     response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
278                     response.addHeader(ERROR, ADD_GROUP_ERROR);
279                     response.addHeader(MESSAGE, message);
280                     return;
281                 }
282                 // policy file copied ok and the Group was updated on the PDP
283                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
284                 response.addHeader("operation", "push");
285                 response.addHeader(POLICYID, policyName);
286                 response.addHeader("groupId", groupId);
287
288                 LOGGER.info("policy '" + policyName + "' copied to directory for group '" + groupId + "'");
289                 loggingContext.transactionEnded();
290                 auditLogger.info(SUCCESS);
291                 LOGGER.info(TRANSENDED);
292             } else if (request.getParameter("default") != null) {
293                 // Args: group=<groupId> default=true <= make default
294                 // change the current default group to be the one identified in
295                 // the request.
296                 loggingContext.setServiceName("AC:PAP.setDefaultGroup");
297                 // This is a POST operation rather than a PUT "update group"
298                 // because of the side-effect that the current default group is
299                 // also changed.
300                 // It should never be the case that multiple groups are
301                 // currently marked as the default, but protect against that
302                 // anyway.
303                 PolicyDbDaoTransaction setDefaultGroupTransaction =
304                         XACMLPapServlet.getPolicyDbDao().getNewTransaction();
305                 try {
306                     setDefaultGroupTransaction.changeDefaultGroup(group, PAPSERVLETDOACPOST);
307                     papEngine.setDefaultGroup(group);
308                     loggingContext.metricStarted();
309                     setDefaultGroupTransaction.commitTransaction();
310                     loggingContext.metricEnded();
311                     PolicyLogger.metrics(ACPOSTCOMMITTRANS);
312                 } catch (Exception e) {
313                     setDefaultGroupTransaction.rollbackTransaction();
314                     PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET, " Unable to set group");
315                     loggingContext.transactionEnded();
316                     PolicyLogger.audit(TRANSACTIONFAILED);
317                     setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
318                             "Unable to set group '" + groupId + "' to default");
319                     return;
320                 }
321                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
322                 if (LOGGER.isDebugEnabled()) {
323                     LOGGER.debug("Group- '" + groupId + "' set to be default");
324                 }
325                 auditLogger.info(SUCCESS);
326                 LOGGER.info(TRANSENDED);
327             } else if (request.getParameter(PDP_ID) != null) {
328                 doAcPostTransaction = XACMLPapServlet.getPolicyDbDao().getNewTransaction();
329                 // Args: group=<groupId> pdpId=<pdpId> <= move PDP to group
330                 loggingContext.setServiceName("AC:PAP.movePDP");
331                 String pdpId = request.getParameter(PDP_ID);
332                 OnapPDP pdp = papEngine.getPDP(pdpId);
333                 final OnapPDPGroup originalGroup = papEngine.getPDPGroup(pdp);
334                 try {
335                     doAcPostTransaction.movePdp(pdp, group, PAPSERVLETDOACPOST);
336                 } catch (Exception e) {
337                     doAcPostTransaction.rollbackTransaction();
338                     PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET,
339                             " Error while moving pdp in the database: " + "pdp=" + pdp.getId() + TO_GROUP
340                                     + group.getId());
341                     throw new PAPException(e.getMessage());
342                 }
343                 papEngine.movePDP(pdp, group);
344                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
345                 if (LOGGER.isDebugEnabled()) {
346                     LOGGER.debug(
347                             "PDP - '" + pdp.getId() + "' moved to group - '" + group.getId() + "' set to be default");
348                 }
349                 // update the status of both the original group and the new one
350                 ((StdPDPGroup) originalGroup).resetStatus();
351                 ((StdPDPGroup) group).resetStatus();
352                 // Need to notify the PDP that it's config may have changed
353                 getPapInstance().pdpChanged(pdp, loggingContext);
354                 loggingContext.metricStarted();
355                 doAcPostTransaction.commitTransaction();
356                 loggingContext.metricEnded();
357                 PolicyLogger.metrics(ACPOSTCOMMITTRANS);
358                 loggingContext.transactionEnded();
359                 auditLogger.info(SUCCESS);
360                 PolicyLogger.audit(TRANSENDED);
361             }
362         } catch (PAPException e) {
363             PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET, " AC POST exception");
364             loggingContext.transactionEnded();
365             PolicyLogger.audit(TRANSACTIONFAILED);
366             setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
367         }
368     }
369
370     /**
371      * Requests from the Admin Console to GET info about the Groups and PDPs.
372      *
373      * @param request the request
374      * @param response the response
375      * @param groupId the group id
376      * @param loggingContext the logging context
377      * @param papEngine the pap engine
378      * @throws IOException Signals that an I/O exception has occurred.
379      */
380     public void doAcGet(HttpServletRequest request, HttpServletResponse response, String groupId,
381             OnapLoggingContext loggingContext, PAPPolicyEngine papEngine) throws IOException {
382         try {
383             String parameterDefault = request.getParameter("default");
384             String pdpId = request.getParameter(PDP_ID);
385             String pdpGroup = request.getParameter("getPDPGroup");
386             if ("".equals(groupId)) {
387                 // request IS from AC but does not identify a group by name
388                 if (parameterDefault != null) {
389                     // Request is for the Default group (whatever its id)
390                     loggingContext.setServiceName("AC:PAP.getDefaultGroup");
391                     OnapPDPGroup group = papEngine.getDefaultGroup();
392                     // convert response object to JSON and include in the
393                     // response
394                     mapperWriteValue(new ObjectMapper(), response, group);
395                     if (LOGGER.isDebugEnabled()) {
396                         LOGGER.debug("GET Default group req from '" + request.getRequestURL() + "'");
397                     }
398                     response.setStatus(HttpServletResponse.SC_OK);
399                     response.setHeader(CONTENT_TYPE, APPLICATION_JSON);
400                     try {
401                         response.getOutputStream().close();
402                     } catch (IOException e) {
403                         LOGGER.error(e);
404                     }
405                     loggingContext.transactionEnded();
406                     auditLogger.info(SUCCESS);
407                     PolicyLogger.audit(TRANSENDED);
408                     return;
409                 } else if (pdpId != null) {
410                     // Request is related to a PDP
411                     if (pdpGroup == null) {
412                         // Request is for the (unspecified) group containing a
413                         // given PDP
414                         loggingContext.setServiceName("AC:PAP.getPDP");
415                         OnapPDP pdp = null;
416                         try {
417                             pdp = papEngine.getPDP(pdpId);
418                         } catch (PAPException e) {
419                             LOGGER.error(e);
420                         }
421                         // convert response object to JSON and include in the
422                         // response
423                         mapperWriteValue(new ObjectMapper(), response, pdp);
424                         if (LOGGER.isDebugEnabled()) {
425                             LOGGER.debug("GET pdp '" + pdpId + "' req from '" + request.getRequestURL() + "'");
426                         }
427                         response.setStatus(HttpServletResponse.SC_OK);
428                         response.setHeader(CONTENT_TYPE, APPLICATION_JSON);
429                         try {
430                             response.getOutputStream().close();
431                         } catch (IOException e) {
432                             LOGGER.error(e);
433                         }
434                         loggingContext.transactionEnded();
435                         auditLogger.info(SUCCESS);
436                         PolicyLogger.audit(TRANSENDED);
437                         return;
438                     } else {
439                         // Request is for the group containing a given PDP
440                         loggingContext.setServiceName("AC:PAP.getGroupForPDP");
441                         OnapPDPGroup group = null;
442                         try {
443                             OnapPDP pdp = papEngine.getPDP(pdpId);
444                             group = papEngine.getPDPGroup(pdp);
445                         } catch (PAPException e) {
446                             LOGGER.error(e);
447                         }
448                         // convert response object to JSON and include in the
449                         // response
450                         mapperWriteValue(new ObjectMapper(), response, group);
451                         if (LOGGER.isDebugEnabled()) {
452                             LOGGER.debug("GET PDP '" + pdpId + "' Group req from '" + request.getRequestURL() + "'");
453                         }
454                         response.setStatus(HttpServletResponse.SC_OK);
455                         response.setHeader(CONTENT_TYPE, APPLICATION_JSON);
456                         try {
457                             response.getOutputStream().close();
458                         } catch (IOException e) {
459                             LOGGER.error(e);
460                         }
461                         loggingContext.transactionEnded();
462                         auditLogger.info(SUCCESS);
463                         PolicyLogger.audit(TRANSENDED);
464                         return;
465                     }
466                 } else {
467                     // request is for top-level properties about all groups
468                     loggingContext.setServiceName("AC:PAP.getAllGroups");
469                     Set<OnapPDPGroup> groups = null;
470                     try {
471                         groups = papEngine.getOnapPDPGroups();
472                     } catch (PAPException e) {
473                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET, " AC Get exception");
474                         loggingContext.transactionEnded();
475                         PolicyLogger.audit(TRANSACTIONFAILED);
476                         setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
477                         return;
478                     }
479                     // convert response object to JSON and include in the
480                     // response
481                     mapperWriteValue(new ObjectMapper(), response, groups);
482                     if (LOGGER.isDebugEnabled()) {
483                         LOGGER.debug("GET All groups req");
484                     }
485                     response.setStatus(HttpServletResponse.SC_OK);
486                     response.setHeader(CONTENT_TYPE, APPLICATION_JSON);
487                     try {
488                         response.getOutputStream().close();
489                     } catch (IOException e) {
490                         LOGGER.error(e);
491                     }
492                     loggingContext.transactionEnded();
493                     auditLogger.info(SUCCESS);
494                     PolicyLogger.audit(TRANSENDED);
495                     return;
496                 }
497             }
498             // for all other GET operations the group must exist before the
499             // operation can be done
500             OnapPDPGroup group = null;
501             try {
502                 group = papEngine.getGroup(groupId);
503             } catch (PAPException e) {
504                 LOGGER.error(e);
505             }
506             if (group == null) {
507                 String message = UNKNOWN_GROUP_ID + groupId + "'";
508                 // for fixing Header Manipulation of Fortify issue
509                 if (!message.matches(REGEX)) {
510                     response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
511                     response.addHeader(ERROR, ADD_GROUP_ERROR);
512                     response.addHeader(MESSAGE, "Group Id is not valid");
513                     return;
514                 }
515                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
516                 loggingContext.transactionEnded();
517                 PolicyLogger.audit(TRANSACTIONFAILED);
518                 setResponseError(response, HttpServletResponse.SC_NOT_FOUND, message);
519                 return;
520             }
521             // Figure out which request this is based on the parameters
522             String policyId = request.getParameter(POLICYID);
523             if (policyId != null) {
524                 // retrieve a policy
525                 loggingContext.setServiceName("AC:PAP.getPolicy");
526                 // convert response object to JSON and include in the response
527                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " GET Policy not implemented");
528                 loggingContext.transactionEnded();
529                 PolicyLogger.audit(TRANSACTIONFAILED);
530                 setResponseError(response, HttpServletResponse.SC_BAD_REQUEST, "GET Policy not implemented");
531             } else {
532                 // No other parameters, so return the identified Group
533                 loggingContext.setServiceName("AC:PAP.getGroup");
534                 // convert response object to JSON and include in the response
535                 mapperWriteValue(new ObjectMapper(), response, group);
536                 if (LOGGER.isDebugEnabled()) {
537                     LOGGER.debug("GET group '" + group.getId() + "' req from '" + request.getRequestURL() + "'");
538                 }
539                 response.setStatus(HttpServletResponse.SC_OK);
540                 response.setHeader(CONTENT_TYPE, APPLICATION_JSON);
541                 try {
542                     response.getOutputStream().close();
543                 } catch (IOException e) {
544                     LOGGER.error(e);
545                 }
546                 loggingContext.transactionEnded();
547                 auditLogger.info(SUCCESS);
548                 PolicyLogger.audit(TRANSENDED);
549                 return;
550             }
551             // Currently there are no other GET calls from the AC.
552             // The AC uses the "GET All Groups" operation to fill its local
553             // cache and uses that cache for all other GETs without calling the
554             // PAP.
555             // Other GETs that could be called:
556             // Specific Group (groupId=<groupId>)
557             // A Policy (groupId=<groupId> policyId=<policyId>)
558             // A PDP (groupId=<groupId> pdpId=<pdpId>)
559             PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " UNIMPLEMENTED ");
560             loggingContext.transactionEnded();
561             PolicyLogger.audit(TRANSACTIONFAILED);
562             setResponseError(response, HttpServletResponse.SC_BAD_REQUEST, UNIMPLEMENTED);
563         } catch (PAPException e) {
564             PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET, " AC Get exception");
565             loggingContext.transactionEnded();
566             PolicyLogger.audit(TRANSACTIONFAILED);
567             setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
568         }
569     }
570
571     /**
572      * Requests from the Admin Console to create new items or update existing ones.
573      *
574      * @param request the request
575      * @param response the response
576      * @param groupId the group id
577      * @param loggingContext the logging context
578      * @param papEngine the pap engine
579      * @throws IOException Signals that an I/O exception has occurred.
580      */
581     public void doAcPut(HttpServletRequest request, HttpServletResponse response, String groupId,
582             OnapLoggingContext loggingContext, PAPPolicyEngine papEngine) throws IOException {
583         PolicyDbDaoTransaction acPutTransaction = XACMLPapServlet.getPolicyDbDao().getNewTransaction();
584         try {
585             String userId = request.getParameter("userId");
586             // for PUT operations the group may or may not need to exist before
587             // the operation can be done
588             OnapPDPGroup group = papEngine.getGroup(groupId);
589             // determine the operation needed based on the parameters in the
590             // request
591             // for remaining operations the group must exist before the
592             // operation can be done
593             if (group == null) {
594                 String message = UNKNOWN_GROUP_ID + groupId + "'";
595                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
596                 loggingContext.transactionEnded();
597                 PolicyLogger.audit(TRANSACTIONFAILED);
598                 setResponseError(response, HttpServletResponse.SC_NOT_FOUND, message);
599                 acPutTransaction.rollbackTransaction();
600                 return;
601             }
602             if (request.getParameter("policy") != null) {
603                 // group=<groupId> policy=<policyId> contents=policy file <=
604                 // Create new policy file in group dir, or replace it if it
605                 // already exists (do not touch properties)
606                 loggingContext.setServiceName("AC:PAP.putPolicy");
607                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE
608                         + " PARTIALLY IMPLEMENTED!!!  ACTUAL CHANGES SHOULD BE MADE BY PAP SERVLET!!! ");
609                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
610                 loggingContext.transactionEnded();
611                 PolicyLogger.audit(TRANSACTIONFAILED);
612                 auditLogger.info(SUCCESS);
613                 PolicyLogger.audit(TRANSENDED);
614                 acPutTransaction.rollbackTransaction();
615             } else if (request.getParameter(PDP_ID) != null) {
616                 // ARGS: group=<groupId> pdpId=<pdpId/URL> <= create a new PDP
617                 // or Update an Existing one
618                 String pdpId = request.getParameter(PDP_ID);
619                 if (papEngine.getPDP(pdpId) == null) {
620                     loggingContext.setServiceName("AC:PAP.createPDP");
621                 } else {
622                     loggingContext.setServiceName("AC:PAP.updatePDP");
623                 }
624                 // get the request content into a String
625                 String json = null;
626                 // read the inputStream into a buffer (trick found online scans
627                 // entire input looking for end-of-file)
628                 try {
629                     Scanner scanner = new Scanner(request.getInputStream());
630                     scanner.useDelimiter("\\A");
631                     json = scanner.hasNext() ? scanner.next() : "";
632                     scanner.close();
633                 } catch (IOException e) {
634                     LOGGER.error(e);
635                 }
636                 LOGGER.info("JSON request from AC: " + json);
637                 // convert Object sent as JSON into local object
638                 ObjectMapper mapper = new ObjectMapper();
639                 Object objectFromJson = null;
640                 try {
641                     objectFromJson = mapper.readValue(json, StdPDP.class);
642                 } catch (Exception e) {
643                     LOGGER.error(e);
644                 }
645                 if (pdpId == null || objectFromJson == null || !(objectFromJson instanceof StdPDP)
646                         || ((StdPDP) objectFromJson).getId() == null
647                         || !((StdPDP) objectFromJson).getId().equals(pdpId)) {
648                     PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " PDP new/update had bad input. pdpId=" + pdpId
649                             + " objectFromJSON=" + objectFromJson);
650                     loggingContext.transactionEnded();
651                     PolicyLogger.audit(TRANSACTIONFAILED);
652                     setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
653                             "Bad input pdpid for object:" + objectFromJson);
654                 }
655                 StdPDP pdp = (StdPDP) objectFromJson;
656                 if (pdp != null) {
657                     OnapPDP origPdp = null;
658                     try {
659                         origPdp = papEngine.getPDP(pdpId);
660                     } catch (PAPException e) {
661                         LOGGER.error(e);
662                     }
663                     if (origPdp == null) {
664                         // this is a request to create a new PDP object
665                         try {
666                             acPutTransaction.addPdpToGroup(pdp.getId(), group.getId(), pdp.getName(),
667                                     pdp.getDescription(), pdp.getJmxPort(), XACML_PAP_SERVLET_DO_AC_PUT);
668                             papEngine.newPDP(pdp.getId(), group, pdp.getName(), pdp.getDescription(), pdp.getJmxPort());
669                         } catch (Exception e) {
670                             PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET,
671                                     " Error while adding pdp to group in the database: " + "pdp=" + (pdp.getId())
672                                             + TO_GROUP + group.getId());
673                             throw new PAPException(e.getMessage());
674                         }
675                     } else {
676                         // this is a request to update the pdp
677                         try {
678                             acPutTransaction.updatePdp(pdp, XACML_PAP_SERVLET_DO_AC_PUT);
679                             papEngine.updatePDP(pdp);
680                         } catch (Exception e) {
681                             PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET,
682                                     " Error while updating pdp in the database: " + "pdp=" + pdp.getId());
683                             throw new PAPException(e.getMessage());
684                         }
685                     }
686                     response.setStatus(HttpServletResponse.SC_NO_CONTENT);
687                     if (LOGGER.isDebugEnabled()) {
688                         LOGGER.debug("PDP '" + pdpId + "' created/updated");
689                     }
690                     // adjust the group's state including the new PDP
691                     ((StdPDPGroup) group).resetStatus();
692                     // this might affect the PDP, so notify it of the change
693                     getPapInstance().pdpChanged(pdp, loggingContext);
694                     loggingContext.metricStarted();
695                     acPutTransaction.commitTransaction();
696                     loggingContext.metricEnded();
697                     PolicyLogger.metrics(XACMLPAPSERVLET_DO_AC_PUT_COMMIT_TRANS);
698                     loggingContext.transactionEnded();
699                     auditLogger.info(SUCCESS);
700                     PolicyLogger.audit(TRANSENDED);
701                 } else {
702                     try {
703                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, XACMLPAPSERVLET,
704                                 " Error while adding pdp to group in the database: " + "pdp=null" + TO_GROUP
705                                         + group.getId());
706                         throw new PAPException("PDP is null");
707                     } catch (Exception e) {
708                         throw new PAPException("PDP is null" + e.getMessage() + e);
709                     }
710                 }
711             } else if (request.getParameter("pipId") != null) {
712                 // group=<groupId> pipId=<pipEngineId> contents=pip properties
713                 // <= add a PIP to pip config, or replace it if it already
714                 // exists (lenient operation)
715                 loggingContext.setServiceName("AC:PAP.putPIP");
716                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + UNIMPLEMENTED);
717                 loggingContext.transactionEnded();
718                 PolicyLogger.audit(TRANSACTIONFAILED);
719                 setResponseError(response, HttpServletResponse.SC_BAD_REQUEST, UNIMPLEMENTED);
720                 acPutTransaction.rollbackTransaction();
721             } else {
722                 // Assume that this is an update of an existing PDP Group
723                 // ARGS: group=<groupId> <= Update an Existing Group
724                 loggingContext.setServiceName("AC:PAP.updateGroup");
725                 // get the request content into a String
726                 String json = null;
727                 // read the inputStream into a buffer (trick found online scans
728                 // entire input looking for end-of-file)
729                 try {
730                     Scanner scanner = new Scanner(request.getInputStream());
731                     scanner.useDelimiter("\\A");
732                     json = scanner.hasNext() ? scanner.next() : "";
733                     scanner.close();
734                 } catch (IOException e) {
735                     LOGGER.error(e);
736                 }
737                 LOGGER.info("JSON request from AC: " + json);
738                 // convert Object sent as JSON into local object
739                 ObjectMapper mapper = new ObjectMapper();
740                 Object objectFromJson = null;
741                 try {
742                     objectFromJson = mapper.readValue(json, StdPDPGroup.class);
743                 } catch (Exception e) {
744                     LOGGER.error(e);
745                 }
746                 if (!(objectFromJson instanceof StdPDPGroup)
747                         || !((StdPDPGroup) objectFromJson).getId().equals(group.getId())) {
748                     PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " Group update had bad input. id="
749                             + group.getId() + " objectFromJSON=" + objectFromJson);
750                     loggingContext.transactionEnded();
751                     PolicyLogger.audit(TRANSACTIONFAILED);
752                     setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
753                             "Bad input id for object:" + objectFromJson);
754                 }
755                 // The Path on the PAP side is not carried on the RESTful
756                 // interface with the AC
757                 // (because it is local to the PAP)
758                 // so we need to fill that in before submitting the group for
759                 // update
760                 if (objectFromJson != null) {
761                     ((StdPDPGroup) objectFromJson).setDirectory(((StdPDPGroup) group).getDirectory());
762                 }
763                 try {
764                     if ("delete".equals(((StdPDPGroup) objectFromJson).getOperation())) {
765                         acPutTransaction.updateGroup((StdPDPGroup) objectFromJson, "XACMLPapServlet.doDelete", userId);
766                     } else {
767                         acPutTransaction.updateGroup((StdPDPGroup) objectFromJson, XACML_PAP_SERVLET_DO_AC_PUT, userId);
768                     }
769                 } catch (Exception e) {
770                     PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW + " Error while updating group in the database: "
771                             + "group=" + group.getId());
772                     LOGGER.error(e);
773                     throw new PAPException(e.getMessage());
774                 }
775
776                 PushPolicyHandler pushPolicyHandler = PushPolicyHandler.getInstance();
777                 OnapPDPGroup updatedGroup = (StdPDPGroup) objectFromJson;
778                 if (pushPolicyHandler.preSafetyCheck(updatedGroup, XACMLPapServlet.getConfigHome())) {
779                     LOGGER.debug("Precheck Successful.");
780                 }
781                 try {
782                     papEngine.updateGroup((StdPDPGroup) objectFromJson);
783                 } catch (PAPException e) {
784                     LOGGER.error(e);
785                 }
786                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
787                 if (LOGGER.isDebugEnabled()) {
788                     LOGGER.debug("Group '" + group.getId() + "' updated");
789                 }
790                 loggingContext.metricStarted();
791                 acPutTransaction.commitTransaction();
792                 loggingContext.metricEnded();
793                 PolicyLogger.metrics(XACMLPAPSERVLET_DO_AC_PUT_COMMIT_TRANS);
794                 // Group changed, which might include changing the policies
795                 getPapInstance().groupChanged(group, loggingContext);
796                 loggingContext.transactionEnded();
797                 auditLogger.info(SUCCESS);
798                 PolicyLogger.audit(TRANSENDED);
799             }
800         } catch (PAPException e) {
801             LOGGER.debug(e);
802             acPutTransaction.rollbackTransaction();
803             PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET, " AC PUT exception");
804             loggingContext.transactionEnded();
805             PolicyLogger.audit(TRANSACTIONFAILED);
806             setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
807         }
808     }
809
810     /**
811      * Requests from the Admin Console to delete/remove items.
812      *
813      * @param request the request
814      * @param response the response
815      * @param groupId the group id
816      * @param loggingContext the logging context
817      * @param papEngine the pap engine
818      * @throws IOException Signals that an I/O exception has occurred.
819      */
820     public void doAcDelete(HttpServletRequest request, HttpServletResponse response, String groupId,
821             OnapLoggingContext loggingContext, PAPPolicyEngine papEngine) throws IOException {
822         PolicyDbDaoTransaction removePdpOrGroupTransaction = XACMLPapServlet.getPolicyDbDao().getNewTransaction();
823         try {
824             // for all DELETE operations the group must exist before the
825             // operation can be done
826             loggingContext.setServiceName("AC:PAP.delete");
827             OnapPDPGroup group = papEngine.getGroup(groupId);
828             if (group == null) {
829                 String message = UNKNOWN_GROUP_ID + groupId + "'";
830                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
831                 loggingContext.transactionEnded();
832                 PolicyLogger.audit(TRANSACTIONFAILED);
833                 setResponseError(response, HttpServletResponse.SC_NOT_FOUND, UNKNOWN_GROUP_ID + groupId + "'");
834                 removePdpOrGroupTransaction.rollbackTransaction();
835                 return;
836             }
837             // determine the operation needed based on the parameters in the
838             // request
839             if (request.getParameter("policy") != null) {
840                 // group=<groupId> policy=<policyId> [delete=<true|false>] <=
841                 // delete policy file from group
842                 loggingContext.setServiceName("AC:PAP.deletePolicy");
843                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + SPACE_UNIMPLEMENTED);
844                 loggingContext.transactionEnded();
845                 PolicyLogger.audit(TRANSACTIONFAILED);
846                 setResponseError(response, HttpServletResponse.SC_BAD_REQUEST, UNIMPLEMENTED);
847                 removePdpOrGroupTransaction.rollbackTransaction();
848             } else if (request.getParameter(PDP_ID) != null) {
849                 // ARGS: group=<groupId> pdpId=<pdpId> <= delete PDP
850                 String pdpId = request.getParameter(PDP_ID);
851                 OnapPDP pdp = papEngine.getPDP(pdpId);
852                 removePdpFromGroup(removePdpOrGroupTransaction, pdp, papEngine);
853                 // adjust the status of the group, which may have changed when
854                 // we removed this PDP
855                 ((StdPDPGroup) group).resetStatus();
856                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
857                 // update the PDP and tell it that it has NO Policies (which
858                 // prevents it from serving PEP Requests)
859                 getPapInstance().pdpChanged(pdp, loggingContext);
860                 loggingContext.metricStarted();
861                 removePdpOrGroupTransaction.commitTransaction();
862                 loggingContext.metricEnded();
863                 PolicyLogger.metrics(XACMLPAPSERVLET_DO_AC_PUT_COMMIT_TRANS);
864                 loggingContext.transactionEnded();
865                 auditLogger.info(SUCCESS);
866                 PolicyLogger.audit(TRANSENDED);
867             } else if (request.getParameter("pipId") != null) {
868                 // group=<groupId> pipId=<pipEngineId> <= delete PIP config for
869                 // given engine
870                 loggingContext.setServiceName("AC:PAP.deletePIPConfig");
871                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + SPACE_UNIMPLEMENTED);
872                 loggingContext.transactionEnded();
873                 PolicyLogger.audit(TRANSACTIONFAILED);
874                 setResponseError(response, HttpServletResponse.SC_BAD_REQUEST, UNIMPLEMENTED);
875                 removePdpOrGroupTransaction.rollbackTransaction();
876             } else {
877                 // ARGS: group=<groupId> movePDPsToGroupId=<movePDPsToGroupId>
878                 // <= delete a group and move all its PDPs to the given group
879                 String moveToGroupId = request.getParameter("movePDPsToGroupId");
880                 OnapPDPGroup moveToGroup = null;
881                 if (moveToGroupId != null) {
882                     try {
883                         moveToGroup = papEngine.getGroup(moveToGroupId);
884                     } catch (PAPException e) {
885                         LOGGER.error(e);
886                     }
887                 }
888                 // get list of PDPs in the group being deleted so we can notify
889                 // them that they got changed
890                 Set<OnapPDP> movedPdps = new HashSet<>();
891                 movedPdps.addAll(group.getOnapPdps());
892                 // do the move/remove
893                 deleteGroup(removePdpOrGroupTransaction, group, moveToGroup, papEngine);
894                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
895                 // notify any PDPs in the removed set that their config may have
896                 // changed
897                 for (OnapPDP pdp : movedPdps) {
898                     getPapInstance().pdpChanged(pdp, loggingContext);
899                 }
900                 loggingContext.metricStarted();
901                 removePdpOrGroupTransaction.commitTransaction();
902                 loggingContext.metricEnded();
903                 PolicyLogger.metrics(XACMLPAPSERVLET_DO_AC_PUT_COMMIT_TRANS);
904                 loggingContext.transactionEnded();
905                 auditLogger.info(SUCCESS);
906                 PolicyLogger.audit(TRANSENDED);
907             }
908         } catch (PAPException e) {
909             removePdpOrGroupTransaction.rollbackTransaction();
910             PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, XACMLPAPSERVLET, " AC DELETE exception");
911             loggingContext.transactionEnded();
912             PolicyLogger.audit(TRANSACTIONFAILED);
913             setResponseError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
914         }
915     }
916
917     private void deleteGroup(PolicyDbDaoTransaction removePdpOrGroupTransaction, OnapPDPGroup group,
918             OnapPDPGroup moveToGroup, PAPPolicyEngine papEngine) throws PAPException {
919         try {
920             removePdpOrGroupTransaction.deleteGroup(group, moveToGroup, "XACMLPapServlet.doACDelete");
921             papEngine.removeGroup(group, moveToGroup);
922         } catch (Exception e) {
923             PolicyLogger.error(MessageCodes.ERROR_UNKNOWN, e, XACMLPAPSERVLET,
924                     " Failed to delete PDP Group. Exception");
925             throw new PAPException(e.getMessage());
926         }
927     }
928
929     private void removePdpFromGroup(PolicyDbDaoTransaction removePdpOrGroupTransaction, OnapPDP pdp,
930             PAPPolicyEngine papEngine) throws PAPException {
931         try {
932             removePdpOrGroupTransaction.removePdpFromGroup(pdp.getId(), "XACMLPapServlet.doACDelete");
933             papEngine.removePDP(pdp);
934         } catch (Exception e) {
935             throw new PAPException(e);
936         }
937     }
938
939     private XACMLPapServlet getPapInstance() {
940         return new XACMLPapServlet();
941     }
942
943     private static void mapperWriteValue(ObjectMapper mapper, HttpServletResponse response, Object value) {
944         try {
945             mapper.writeValue(response.getOutputStream(), value);
946         } catch (Exception e) {
947             LOGGER.error(e);
948         }
949     }
950
951     private void setResponseError(HttpServletResponse response, int responseCode, String message) {
952         try {
953             if (message != null && !message.isEmpty()) {
954                 response.sendError(responseCode, message);
955             }
956         } catch (IOException e) {
957             LOGGER.error("Error setting Error response Header ", e);
958         }
959     }
960 }