d095bbdb1498eb552f600d4f11a4f7ecf23fd749
[portal.git] / ecomp-portal-BE-common / src / main / java / org / openecomp / portalapp / portal / logging / aop / EPEELFLoggerAdvice.java
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed
9  * under the Apache License, Version 2.0 (the “License”);
10  * you may not use this software except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
37  */
38 package org.openecomp.portalapp.portal.logging.aop;
39
40 import java.net.InetAddress;
41 import java.text.SimpleDateFormat;
42 import java.util.Date;
43 import java.util.UUID;
44
45 import javax.servlet.http.HttpServletRequest;
46
47 import org.openecomp.portalapp.portal.domain.EPUser;
48 import org.openecomp.portalapp.portal.utils.EPCommonSystemProperties;
49 import org.openecomp.portalapp.util.EPUserUtils;
50 import org.openecomp.portalsdk.core.exception.SessionExpiredException;
51 import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
52 import org.openecomp.portalsdk.core.logging.format.AuditLogFormatter;
53 import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
54 import org.openecomp.portalsdk.core.util.SystemProperties;
55 import org.openecomp.portalsdk.core.util.SystemProperties.SecurityEventTypeEnum;
56 import org.openecomp.portalsdk.core.web.support.UserUtils;
57 import org.slf4j.MDC;
58
59 import com.att.eelf.configuration.Configuration;
60
61 @org.springframework.context.annotation.Configuration
62 public class EPEELFLoggerAdvice {
63
64         private EELFLoggerDelegate adviceLogger = EELFLoggerDelegate.getLogger(EPEELFLoggerAdvice.class);
65
66         /**
67          * DateTime Format according to the ECOMP Application Logging Guidelines.
68          */
69         private static final SimpleDateFormat ecompLogDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
70
71         /**
72          * @return Current date and time in the format specified by the ECOMP
73          *         Application Logging Guidelines.
74          */
75         public static String getCurrentDateTimeUTC() {
76                 String currentDateTime = ecompLogDateFormat.format(new Date());
77                 return currentDateTime;
78         }
79
80         /**
81          * Sets logging context with values from HttpServletRequest object.
82          * 
83          * @param req
84          *            HttpServletRequest
85          * @param securityEventType
86          *            SecurityEventTypeEnum
87          */
88         public void loadServletRequestBasedDefaults(HttpServletRequest req, SecurityEventTypeEnum securityEventType) {
89                 try {
90                         setHttpRequestBasedDefaultsIntoGlobalLoggingContext(req, securityEventType, req.getServletPath());
91                 } catch (Exception e) {
92                         adviceLogger.error(EELFLoggerDelegate.errorLogger, "loadServletRequestBasedDefaults failed", e);
93                 }
94         }
95
96         /**
97          * 
98          * @param securityEventType
99          * @param args
100          * @param passOnArgs
101          * @return Object array
102          */
103         public Object[] before(SecurityEventTypeEnum securityEventType, Object[] args, Object[] passOnArgs) {
104                 String className = "";
105                 if (passOnArgs.length > 0 && passOnArgs[0] != null)
106                         className = passOnArgs[0].toString();
107                 String methodName = "";
108                 if (passOnArgs.length > 1 && passOnArgs[1] != null)
109                         methodName = passOnArgs[1].toString();
110
111                 // Initialize Request defaults only for controller methods.
112                 MDC.put(className + methodName + EPCommonSystemProperties.METRICSLOG_BEGIN_TIMESTAMP, getCurrentDateTimeUTC());
113                 MDC.put(EPCommonSystemProperties.TARGET_ENTITY, EPCommonSystemProperties.ECOMP_PORTAL_BE);
114                 MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, methodName);
115                 if (securityEventType != null) {
116                         MDC.put(className + methodName + EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP,
117                                         getCurrentDateTimeUTC());
118                         HttpServletRequest req = null;
119                         if (args.length > 0 && args[0] != null && args[0] instanceof HttpServletRequest) {
120                                 req = (HttpServletRequest) args[0];
121                                 this.setHttpRequestBasedDefaultsIntoGlobalLoggingContext(req, securityEventType, methodName);
122                         }
123                 }
124
125                 EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
126                 logger.debug(EELFLoggerDelegate.debugLogger, "EPEELFLoggerAdvice#before: entering {}", methodName);
127                 return new Object[] { "" };
128         }
129
130         /**
131          * 
132          * @param securityEventType
133          * @param statusCode
134          * @param responseCode
135          * @param args
136          * @param returnArgs
137          * @param passOnArgs
138          */
139         public void after(SecurityEventTypeEnum securityEventType, String statusCode, String responseCode, Object[] args,
140                         Object[] returnArgs, Object[] passOnArgs) {
141                 String className = "";
142                 if (passOnArgs.length > 0 && passOnArgs[0] != null)
143                         className = passOnArgs[0].toString();
144                 // Method Name
145                 String methodName = "";
146                 if (passOnArgs.length > 1 && passOnArgs[1] != null)
147                         methodName = passOnArgs[1].toString();
148
149                 if (MDC.get(EPCommonSystemProperties.TARGET_SERVICE_NAME) == null
150                                 || MDC.get(EPCommonSystemProperties.TARGET_SERVICE_NAME) == "")
151                         MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, methodName);
152
153                 if (MDC.get(EPCommonSystemProperties.TARGET_ENTITY) == null
154                                 || MDC.get(EPCommonSystemProperties.TARGET_ENTITY) == "")
155                         MDC.put(EPCommonSystemProperties.TARGET_ENTITY, EPCommonSystemProperties.ECOMP_PORTAL_BE);
156
157                 MDC.put(EPCommonSystemProperties.METRICSLOG_BEGIN_TIMESTAMP,
158                                 MDC.get(className + methodName + EPCommonSystemProperties.METRICSLOG_BEGIN_TIMESTAMP));
159                 MDC.put(EPCommonSystemProperties.METRICSLOG_END_TIMESTAMP, getCurrentDateTimeUTC());
160                 this.calculateDateTimeDifference(MDC.get(EPCommonSystemProperties.METRICSLOG_BEGIN_TIMESTAMP),
161                                 MDC.get(EPCommonSystemProperties.METRICSLOG_END_TIMESTAMP));
162
163                 // Making sure to reload the INCOMING request MDC defaults if they have
164                 // been wiped out by either Outgoing or LDAP Phone book search
165                 // operations.
166                 if (securityEventType != null && args.length > 0 && args[0] != null && args[0] instanceof HttpServletRequest
167                                 && securityEventType == SecurityEventTypeEnum.INCOMING_REST_MESSAGE
168                                 && (MDC.get(EPCommonSystemProperties.FULL_URL) == null
169                                                 || MDC.get(EPCommonSystemProperties.FULL_URL) == "")) {
170                         HttpServletRequest req = (HttpServletRequest) args[0];
171                         this.setHttpRequestBasedDefaultsIntoGlobalLoggingContext(req, securityEventType, methodName);
172                 }
173
174                 // Use external API response code in case if it resulted in an error.
175                 String externalAPIResponseCode = MDC.get(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE);
176                 if (externalAPIResponseCode == null || externalAPIResponseCode == ""
177                                 || externalAPIResponseCode.trim().equalsIgnoreCase("200")) {
178                         MDC.put(EPCommonSystemProperties.RESPONSE_CODE, responseCode);
179                         MDC.put(EPCommonSystemProperties.STATUS_CODE, statusCode);
180                 } else {
181                         MDC.put(EPCommonSystemProperties.RESPONSE_CODE, externalAPIResponseCode);
182                         MDC.put(EPCommonSystemProperties.STATUS_CODE, "ERROR");
183                 }
184
185                 EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
186                 logger.debug(EELFLoggerDelegate.debugLogger, "EPEELFLoggerAdvice#after: finished {}", methodName);
187                 // add the metrics log
188                 logger.info(EELFLoggerDelegate.metricsLogger,  methodName + " operation is completed.");
189
190                 // Log security message, if necessary
191                 if (securityEventType != null) {
192                         MDC.put(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP,
193                                         MDC.get(className + methodName + EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP));
194                         MDC.put(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP, getCurrentDateTimeUTC());
195                         this.calculateDateTimeDifference(MDC.get(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP),
196                                         MDC.get(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP));
197
198                         this.logSecurityMessage(logger, securityEventType, methodName);
199
200                         // Outgoing & LDAP messages are part of Incoming requests so,
201                         // keep "RequestId", "PartnerName", "ServiceName", "LoginId" &
202                         // "ResponseCode" etc. in memory and remove it only when
203                         // finished processing the parent incoming message.
204                         if (securityEventType != SecurityEventTypeEnum.OUTGOING_REST_MESSAGE
205                                         && securityEventType != SecurityEventTypeEnum.LDAP_PHONEBOOK_USER_SEARCH) {
206                                 MDC.remove(Configuration.MDC_KEY_REQUEST_ID);
207                                 MDC.remove(EPCommonSystemProperties.PARTNER_NAME);
208                                 MDC.remove(Configuration.MDC_SERVICE_NAME);
209                                 MDC.remove(EPCommonSystemProperties.MDC_LOGIN_ID);
210                                 MDC.remove(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE);
211                         }
212
213                         // clear when finishes audit logging
214                         MDC.remove(EPCommonSystemProperties.FULL_URL);
215                         MDC.remove(EPCommonSystemProperties.PROTOCOL);
216                         MDC.remove(EPCommonSystemProperties.STATUS_CODE);
217                         MDC.remove(className + methodName + EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
218                         MDC.remove(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
219                         MDC.remove(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP);
220                         MDC.remove(EPCommonSystemProperties.RESPONSE_CODE);
221                 }
222                 MDC.remove(className + methodName + EPCommonSystemProperties.METRICSLOG_BEGIN_TIMESTAMP);
223                 MDC.remove(EPCommonSystemProperties.METRICSLOG_BEGIN_TIMESTAMP);
224                 MDC.remove(EPCommonSystemProperties.METRICSLOG_END_TIMESTAMP);
225                 MDC.remove(EPCommonSystemProperties.MDC_TIMER);
226                 MDC.remove(EPCommonSystemProperties.TARGET_ENTITY);
227                 MDC.remove(EPCommonSystemProperties.TARGET_SERVICE_NAME);
228         }
229
230         /**
231          * 
232          * @param logger
233          * @param securityEventType
234          * @param restMethod
235          */
236         private void logSecurityMessage(EELFLoggerDelegate logger, SecurityEventTypeEnum securityEventType,
237                         String restMethod) {
238                 StringBuilder additionalInfoAppender = new StringBuilder();
239                 String auditMessage = "";
240
241                 if (securityEventType == SecurityEventTypeEnum.OUTGOING_REST_MESSAGE) {
242                         additionalInfoAppender.append(String.format("%s '%s' request was initiated.", restMethod,
243                                         MDC.get(EPCommonSystemProperties.TARGET_SERVICE_NAME)));
244                 } else if (securityEventType == SecurityEventTypeEnum.LDAP_PHONEBOOK_USER_SEARCH) {
245                         additionalInfoAppender.append("LDAP Phonebook search operation is performed.");
246                 } else {
247                         additionalInfoAppender.append(String.format("%s request was received.", restMethod));
248
249                         if (securityEventType == SecurityEventTypeEnum.FE_LOGIN_ATTEMPT) {
250                                 String loginId = "";
251                                 String additionalMessage = " Successfully authenticated.";
252                                 loginId = MDC.get(EPCommonSystemProperties.MDC_LOGIN_ID);
253                                 if (loginId == null || loginId == "" || loginId == EPCommonSystemProperties.UNKNOWN) {
254                                         additionalMessage = " No cookies are found.";
255                                 }
256                                 additionalInfoAppender.append(additionalMessage);
257                         } else if (securityEventType == SecurityEventTypeEnum.FE_LOGOUT) {
258                                 additionalInfoAppender.append(" User has been successfully logged out.");
259                         }
260                 }
261
262                 String fullURL = MDC.get(EPCommonSystemProperties.FULL_URL);
263                 if (fullURL != null && fullURL != "") {
264                         additionalInfoAppender.append(" Request-URL:" + MDC.get(EPCommonSystemProperties.FULL_URL));
265                 }
266
267                 auditMessage = AuditLogFormatter.getInstance().createMessage(MDC.get(EPCommonSystemProperties.PROTOCOL),
268                                 securityEventType.name(), MDC.get(EPCommonSystemProperties.MDC_LOGIN_ID),
269                                 additionalInfoAppender.toString());
270
271                 logger.info(EELFLoggerDelegate.auditLogger, auditMessage);
272         }
273
274         /**
275          * 
276          * @param req
277          * @param securityEventType
278          * @param restMethod
279          */
280         private void setHttpRequestBasedDefaultsIntoGlobalLoggingContext(HttpServletRequest req,
281                         SecurityEventTypeEnum securityEventType, String restMethod) {
282                 /**
283                  * No need to load the request based defaults for the following security
284                  * messages since either they are initiated by the Portal BE or not Http
285                  * request based.
286                  */
287                 if (req != null) {
288                         if (securityEventType != SecurityEventTypeEnum.OUTGOING_REST_MESSAGE
289                                         && securityEventType != SecurityEventTypeEnum.LDAP_PHONEBOOK_USER_SEARCH
290                                         && securityEventType != SecurityEventTypeEnum.INCOMING_UEB_MESSAGE) {
291                                 // Load the RequestID (aka TrasactionId) into MDC context.
292                                 String requestId = UserUtils.getRequestId(req);
293                                 if (requestId == "" || requestId == null) {
294                                         requestId = UUID.randomUUID().toString();
295                                 }
296                                 MDC.put(Configuration.MDC_KEY_REQUEST_ID, requestId);
297
298                                 // Load user agent into MDC context, if available.
299                                 String accessingClient = "Unknown";
300                                 accessingClient = req.getHeader(SystemProperties.USERAGENT_NAME);
301                                 if (accessingClient != null && accessingClient != "" && (accessingClient.contains("Mozilla")
302                                                 || accessingClient.contains("Chrome") || accessingClient.contains("Safari"))) {
303                                         accessingClient = EPCommonSystemProperties.ECOMP_PORTAL_FE;
304                                 }
305                                 MDC.put(EPCommonSystemProperties.PARTNER_NAME, accessingClient);
306
307                                 // Load loginId into MDC context.
308                                 EPUser user = null;
309                                 try {
310                                         user = EPUserUtils.getUserSession(req);
311                                 } catch (SessionExpiredException se) {
312                                         adviceLogger.debug(EELFLoggerDelegate.debugLogger,
313                                                         "setHttpRequestBasedDefaultsIntoGlobalLoggingContext: No user found in session");
314                                 }
315
316                                 MDC.put(EPCommonSystemProperties.MDC_LOGIN_ID, (user != null ? user.getOrgUserId() : "NoUser"));
317
318                                 // Rest URL & Protocol
319                                 String restURL = "";
320                                 MDC.put(EPCommonSystemProperties.FULL_URL, EPCommonSystemProperties.UNKNOWN);
321                                 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP);
322                                 restURL = UserUtils.getFullURL(req);
323                                 if (restURL != null && restURL != "") {
324                                         MDC.put(EPCommonSystemProperties.FULL_URL, restURL);
325                                         if (restURL.toLowerCase().contains("https")) {
326                                                 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS);
327                                         }
328                                 }
329
330                                 // Rest Path
331                                 MDC.put(Configuration.MDC_SERVICE_NAME, restMethod);
332                                 String restPath = req.getServletPath();
333                                 if (restPath != null && restPath != "") {
334                                         MDC.put(Configuration.MDC_SERVICE_NAME, restPath);
335                                 }
336
337                                 // Client IPAddress i.e. IPAddress of the remote host who is
338                                 // making this request.
339                                 String clientIPAddress = "";
340                                 clientIPAddress = req.getHeader("X-FORWARDED-FOR");
341                                 if (clientIPAddress == null) {
342                                         clientIPAddress = req.getRemoteAddr();
343                                 }
344                                 MDC.put(EPCommonSystemProperties.CLIENT_IP_ADDRESS, clientIPAddress);
345                         } else if (securityEventType == SecurityEventTypeEnum.LDAP_PHONEBOOK_USER_SEARCH) {
346                                 MDC.put(EPCommonSystemProperties.TARGET_ENTITY, "Phonebook");
347                                 MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, "search");
348                         }
349                 } else {
350                         MDC.put(Configuration.MDC_SERVICE_NAME, restMethod);
351                         MDC.put(EPCommonSystemProperties.PARTNER_NAME, EPCommonSystemProperties.ECOMP_PORTAL_FE);
352                 }
353
354                 MDC.put(Configuration.MDC_SERVICE_INSTANCE_ID, "");
355                 MDC.put(Configuration.MDC_ALERT_SEVERITY, AlarmSeverityEnum.INFORMATIONAL.toString());
356                 try {
357                         MDC.put(Configuration.MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
358                         MDC.put(Configuration.MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
359                         MDC.put(Configuration.MDC_INSTANCE_UUID, SystemProperties.getProperty(SystemProperties.INSTANCE_UUID));
360                 } catch (Exception e) {
361                         adviceLogger.error(EELFLoggerDelegate.errorLogger,
362                                         "setHttpRequestBasedDefaultsIntoGlobalLoggingContext failed", e);
363                 }
364         }
365
366         /**
367          * 
368          * @param beginDateTime
369          * @param endDateTime
370          */
371         private void calculateDateTimeDifference(String beginDateTime, String endDateTime) {
372                 if (beginDateTime != null && endDateTime != null) {
373                         try {
374                                 Date beginDate = ecompLogDateFormat.parse(beginDateTime);
375                                 Date endDate = ecompLogDateFormat.parse(endDateTime);
376                                 String timeDifference = String.format("%d", endDate.getTime() - beginDate.getTime());
377                                 MDC.put(SystemProperties.MDC_TIMER, timeDifference);
378                         } catch (Exception e) {
379                                 adviceLogger.error(EELFLoggerDelegate.errorLogger, "calculateDateTimeDifference failed", e);
380                         }
381                 }
382         }
383
384         public String getInternalResponseCode() {
385                 return MDC.get(EPCommonSystemProperties.RESPONSE_CODE);
386         }
387 }