2 * ============LICENSE_START=======================================================
\r
4 * ================================================================================
\r
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
\r
6 * Copyright © 2017-2018 Amdocs
\r
7 * ================================================================================
\r
8 * Licensed under the Apache License, Version 2.0 (the "License");
\r
9 * you may not use this file except in compliance with the License.
\r
10 * You may obtain a copy of the License at
\r
12 * http://www.apache.org/licenses/LICENSE-2.0
\r
14 * Unless required by applicable law or agreed to in writing, software
\r
15 * distributed under the License is distributed on an "AS IS" BASIS,
\r
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
17 * See the License for the specific language governing permissions and
\r
18 * limitations under the License.
\r
19 * ============LICENSE_END=========================================================
\r
21 package org.onap.aai.datarouter.service;
\r
23 import java.util.ArrayList;
\r
24 import java.util.HashMap;
\r
25 import java.util.List;
\r
26 import java.util.Map;
\r
27 import java.util.UUID;
\r
28 import javax.servlet.http.HttpServletRequest;
\r
29 import javax.ws.rs.Consumes;
\r
30 import javax.ws.rs.Encoded;
\r
31 import javax.ws.rs.POST;
\r
32 import javax.ws.rs.Path;
\r
33 import javax.ws.rs.PathParam;
\r
34 import javax.ws.rs.Produces;
\r
35 import javax.ws.rs.core.Context;
\r
36 import javax.ws.rs.core.HttpHeaders;
\r
37 import javax.ws.rs.core.MediaType;
\r
38 import javax.ws.rs.core.Response;
\r
39 import javax.ws.rs.core.Response.Status;
\r
40 import javax.ws.rs.core.UriInfo;
\r
41 import org.onap.aai.cl.api.Logger;
\r
42 import org.onap.aai.cl.eelf.LoggerFactory;
\r
43 import org.onap.aai.cl.mdc.MdcContext;
\r
44 import org.onap.aai.datarouter.entity.POAAuditEvent;
\r
45 import org.onap.aai.datarouter.entity.POAServiceInstanceEntity;
\r
46 import org.onap.aai.datarouter.exception.POAAuditException;
\r
47 import org.onap.aai.datarouter.logging.DataRouterMsgs;
\r
48 import org.onap.aai.datarouter.util.LoggingUtil;
\r
49 import org.onap.aai.event.api.EventPublisher;
\r
50 import org.onap.aai.datarouter.util.DataRouterConstants;
\r
51 import org.onap.aai.restclient.client.Headers;
\r
53 public class AuditService {
\r
55 private static Logger logger = LoggerFactory.getInstance().getLogger(AuditService.class.getName());
\r
56 private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(AuditService.class.getName());
\r
58 private static final String MEDIA_TYPE = MediaType.APPLICATION_JSON;
\r
59 private static final String UNKNOWN_APP = "[unknown_app_id]";
\r
60 private static final String RESULT_OK = "200 OK";
\r
62 private EventPublisher publisher;
\r
64 public AuditService(EventPublisher publisher) throws Exception {
\r
65 this.publisher = publisher;
\r
70 * Handles an incoming post-orchestration audit request.
\r
71 * Generates and posts audit events to DMaaP.
\r
73 * @param content - JSON structure containing the request payload
\r
74 * @param uri - Http request uri
\r
75 * @param headers - Http request headers
\r
76 * @param uriInfo - Http URI info field
\r
77 * @param req - Http request structure.
\r
78 * @return - Standard HTTP response.
\r
82 @Path("/orchestration-event/")
\r
83 @Consumes({MediaType.APPLICATION_JSON})
\r
84 @Produces({MediaType.APPLICATION_JSON})
\r
85 public Response triggerPOA(String content,
\r
86 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
\r
87 @Context HttpServletRequest req) {
\r
89 logger.debug("Incoming request..." + content);
\r
90 Response response = null;
\r
92 Map<String, String> headerAttributes = initializeLogging(req, headers);
\r
94 List<String> serviceInstanceEvents = generateServiceInstanceEvents(headerAttributes, content);
\r
95 processEvent(serviceInstanceEvents);
\r
97 response = Response.status(Status.OK).entity(RESULT_OK).type(MEDIA_TYPE).build();
\r
98 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
\r
100 } catch(POAAuditException e) {
\r
101 response = Response.status(e.getHttpStatus()).entity(e.getMessage()).build();
\r
102 LoggingUtil.logRestRequest(logger, auditLogger, req, response, e);
\r
104 LoggingUtil.closeMdc();
\r
111 * Initialize MDC logging using attributes from the request
\r
113 * @param httpHeaders
\r
114 * @return Returns a map of required header attributes
\r
115 * @throws POAAuditException
\r
117 private Map<String, String> initializeLogging(HttpServletRequest httpReq, HttpHeaders httpHeaders) throws POAAuditException {
\r
119 Map<String, String> headers = new HashMap<String, String>();
\r
120 String remoteAddr = httpReq.getRemoteAddr();
\r
122 if (httpHeaders.getRequestHeaders() == null) {
\r
123 String error="Missing Header";
\r
124 throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error);
\r
126 String transactionId = httpHeaders.getRequestHeaders().getFirst(Headers.TRANSACTION_ID);
\r
127 if((transactionId == null) || transactionId.trim().isEmpty()) {
\r
128 transactionId = UUID.randomUUID().toString();
\r
129 logger.debug("Header " + Headers.TRANSACTION_ID + "not present in request, generating new value: " + transactionId);
\r
131 headers.put(Headers.TRANSACTION_ID, transactionId);
\r
133 String fromAppId = httpHeaders.getRequestHeaders().getFirst(Headers.FROM_APP_ID);
\r
134 if((fromAppId == null) || fromAppId.trim().isEmpty()) {
\r
135 // initialize the context before throwing the exception
\r
136 MdcContext.initialize(transactionId, DataRouterConstants.DATA_ROUTER_SERVICE_NAME, "", UNKNOWN_APP, remoteAddr);
\r
137 String error = "Missing header attribute: " + Headers.FROM_APP_ID;
\r
138 throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error);
\r
140 headers.put(Headers.FROM_APP_ID, fromAppId);
\r
142 LoggingUtil.initMdc(transactionId, fromAppId, remoteAddr);
\r
150 * Extracts service instances and generates a list of events
\r
151 * @param eventHeaders
\r
152 * @param requestBody
\r
153 * @return Returns a list of service instances
\r
154 * @throws POAAuditException if the request contains errors
\r
156 private List<String> generateServiceInstanceEvents(Map<String, String> eventHeaders, String requestBody) throws POAAuditException {
\r
158 POAAuditEvent auditEvent = POAAuditEvent.fromJson(requestBody);
\r
159 auditEvent.validate();
\r
161 List<String> eventMessages = new ArrayList<String>();
\r
162 for (POAServiceInstanceEntity serviceInstance: auditEvent.getServiceInstanceList()) {
\r
163 serviceInstance.validate();
\r
164 serviceInstance.setxFromAppId(eventHeaders.get(Headers.FROM_APP_ID));
\r
165 serviceInstance.setxTransactionId(eventHeaders.get(Headers.TRANSACTION_ID));
\r
166 eventMessages.add(serviceInstance.toJson());
\r
168 return eventMessages;
\r
172 * Publish events to DMaaP.
\r
173 * @param eventMessages
\r
174 * @throws POAAuditException
\r
176 * Note: The Default Transport Type in the DMaaPEventPublisher is defined as "HTTPAAF". Based on the deployment of DMaap, currently
\r
177 * by default the "HTTPAUTH" transport type is supported.
\r
179 private void processEvent(List<String> eventMessages) throws POAAuditException {
\r
181 int messagesSent = 0;
\r
183 messagesSent = publisher.sendSync(eventMessages);
\r
184 logger.debug("The number of messages successfully sent: "+ messagesSent);
\r
186 if (messagesSent > 0) {
\r
187 logger.debug("Published Message: " + eventMessages);
\r
189 String exceptionStr = String.format("Failed to publish %d event(s) to DMaaP", eventMessages.size());
\r
190 logger.debug(exceptionStr);
\r
194 } catch (Exception e) {
\r
195 throw new POAAuditException("Failed to publish event to DMaaP: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR,
\r
196 DataRouterMsgs.EXCEPTION_DURING_METHOD_CALL, e.getMessage());
\r