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