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