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