9863d8f9048ac9eaf93259355c0912856c8f6116
[sdc.git] /
1 package org.openecomp.sdc.securityutil.filters;
2
3 import org.openecomp.sdc.securityutil.AuthenticationCookieUtils;
4 import org.openecomp.sdc.securityutil.CipherUtilException;
5 import org.openecomp.sdc.securityutil.ISessionValidationFilterConfiguration;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8
9 import javax.servlet.Filter;
10 import javax.servlet.FilterChain;
11 import javax.servlet.FilterConfig;
12 import javax.servlet.ServletException;
13 import javax.servlet.ServletRequest;
14 import javax.servlet.ServletResponse;
15 import javax.servlet.http.Cookie;
16 import javax.servlet.http.HttpServletRequest;
17 import javax.servlet.http.HttpServletResponse;
18 import java.io.IOException;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.concurrent.TimeUnit;
22 import java.util.stream.Collectors;
23
24 public abstract class SessionValidationFilter implements Filter {
25     private static final Logger log = LoggerFactory.getLogger(SessionValidationFilter.class.getName());
26     private ISessionValidationFilterConfiguration filterConfiguration;
27     private List<String> excludedUrls;
28
29     public abstract ISessionValidationFilterConfiguration getFilterConfiguration();
30     protected abstract Cookie addRoleToCookie(Cookie updatedCookie);
31     protected abstract boolean isRoleValid(Cookie cookie);
32
33     @Override
34     public final void init(FilterConfig filterConfig) throws ServletException {
35         filterConfiguration = getFilterConfiguration();
36         excludedUrls = filterConfiguration.getExcludedUrls();
37     }
38
39     @Override
40     public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
41         final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
42         final HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
43
44         long starTime = System.nanoTime();
45         log.debug("SessionValidationFilter: Validation started, received request with URL {}", httpRequest.getRequestURL());
46
47         // request preprocessing
48         boolean isContinueProcessing = preProcessingRequest(servletRequest, servletResponse, filterChain, httpRequest, httpResponse);
49         List<Cookie> cookies = null;
50
51         // request processing
52         if (isContinueProcessing) {
53             cookies = extractAuthenticationCookies(httpRequest.getCookies());
54             isContinueProcessing = processRequest(httpRequest, httpResponse, cookies.get(0));
55         }
56
57         // response processing
58         if(isContinueProcessing){
59             log.debug("SessionValidationFilter: Cookie from request {} is valid, passing request to session extension ...", httpRequest.getRequestURL());
60             Cookie updatedCookie = processResponse(cookies.get(cookies.size()-1));
61
62             cleanResponceFromLeftoverCookies(httpResponse, cookies);
63
64             // Use responce wrapper if servlet remove Cookie header from responce
65 //            OutputStream out = httpResponse.getOutputStream();
66 //            ResponceWrapper responceWrapper = new ResponceWrapper(httpResponse);
67
68             log.debug("SessionValidationFilter: request {} passed all validations, passing request to endpoint ...", httpRequest.getRequestURL());
69             httpResponse.addCookie(updatedCookie);
70             filterChain.doFilter(servletRequest, httpResponse);
71
72             // Use responce wrapper if servlet remove Cookie header from responce
73 //            responceWrapper.addCookie(updatedCookie);
74 //            httpResponse.setContentLength(responceWrapper.getData().length);
75 //            out.write(responceWrapper.getData());
76 //            out.close();
77         }
78         long durationSec = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - starTime);
79         long durationMil = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - starTime);
80         log.debug("SessionValidationFilter: Validation ended, running time for URL {} is: {} seconds {} miliseconds", httpRequest.getPathInfo(), durationSec, durationMil);
81     }
82
83
84     private boolean preProcessingRequest(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException {
85
86         boolean isPreProcessingSucceeded = true;
87         if (isUrlFromWhiteList(httpRequest)) {
88             log.debug("SessionValidationFilter: URL {} excluded from access validation , passing request to endpoint ... ", httpRequest.getRequestURL());
89             filterChain.doFilter(servletRequest, servletResponse);
90             isPreProcessingSucceeded = false;
91
92         } else if (!isCookiePresent(httpRequest.getCookies())) {
93             //redirect to portal app
94             log.debug("SessionValidationFilter: Cookie from request {} is not valid, redirecting request to portal", httpRequest.getRequestURL());
95             httpResponse.sendRedirect(filterConfiguration.getRedirectURL());
96             isPreProcessingSucceeded = false;
97         }
98         return isPreProcessingSucceeded;
99     }
100
101     private boolean processRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse, Cookie cookie) throws IOException {
102         boolean isProcessSuccessful= true;
103         try {
104             if (AuthenticationCookieUtils.isSessionExpired(cookie, filterConfiguration)) {
105                 //redirect to portal app
106                 log.debug("SessionValidationFilter: Session is expired, redirecting request {} to portal", httpRequest.getRequestURL());
107                 httpResponse.sendRedirect(filterConfiguration.getRedirectURL());
108                 isProcessSuccessful = false;
109             }
110         } catch (CipherUtilException e) {
111             log.error("SessionValidationFilter: Cookie decryption error : {}", e.getMessage());
112             log.debug("SessionValidationFilter: Cookie decryption error : {}", e.getMessage(), e);
113             isProcessSuccessful = false;
114         }
115
116         if (!isRoleValid(cookie)) {
117             //redirect to portal app
118             log.debug("SessionValidationFilter: Role is not valid, redirecting request {} to portal", httpRequest.getRequestURL());
119             httpResponse.sendRedirect(filterConfiguration.getRedirectURL());
120             isProcessSuccessful = false;
121         }
122         return isProcessSuccessful;
123     }
124
125     private Cookie processResponse(Cookie cookie) throws IOException, ServletException {
126         Cookie updatedCookie;
127         try {
128             updatedCookie = AuthenticationCookieUtils.updateSessionTime(cookie, filterConfiguration);
129         } catch (CipherUtilException e) {
130             log.error("SessionValidationFilter: Cookie cipher error ...");
131             log.debug("SessionValidationFilter: Cookie cipher error : {}", e.getMessage(), e);
132             throw new ServletException(e.getMessage());
133         }
134         updatedCookie = addRoleToCookie(updatedCookie);
135         return updatedCookie;
136     }
137
138     private boolean isCookiePresent(Cookie[] cookies) {
139         if (cookies == null) {
140             return false;
141         }
142         String actualCookieName = filterConfiguration.getCookieName();
143         boolean isPresent = Arrays.stream(cookies).anyMatch(c -> isCookieNameMatch(actualCookieName, c));
144         if (!isPresent) {
145             log.error("SessionValidationFilter: Session Validation Cookie missing ...");
146             return false;
147         }
148         return true;
149     }
150
151     private List<Cookie> extractAuthenticationCookies(Cookie[] cookies) {
152         String actualCookieName = filterConfiguration.getCookieName();
153         log.debug("SessionValidationFilter: Extracting authentication cookies, {} cookies in request", cookies.length);
154         List<Cookie> authenticationCookies = Arrays.stream(cookies).filter(c -> isCookieNameMatch(actualCookieName, c)).collect(Collectors.toList());
155         log.debug("SessionValidationFilter: Extracted {} authentication cookies from request", authenticationCookies.size());
156         if( authenticationCookies.size() > 1 ){
157             authenticationCookies.forEach( cookie -> log.debug("SessionValidationFilter: Multiple cookies found cookie name, {} cookie value {}", cookie.getName(), cookie.getValue()));
158         }
159         return authenticationCookies;
160     }
161
162
163     // use contains for matching due issue with ecomp portal ( change cookie name, add prefix ), temp solution
164     private boolean isCookieNameMatch(String actualCookieName, Cookie c) {
165         return c.getName().contains(actualCookieName);
166     }
167
168     private boolean isUrlFromWhiteList(HttpServletRequest httpRequest) {
169         if (httpRequest.getPathInfo() == null){
170             final String servletPath = httpRequest.getServletPath().toLowerCase();
171             log.debug("SessionValidationFilter: pathInfo is null, trying to check by servlet path white list validation -> ServletPath: {} ", servletPath);
172             return excludedUrls.stream().
173                     anyMatch( e -> servletPath.matches(e));
174         }
175         String pathInfo = httpRequest.getPathInfo().toLowerCase();
176         log.debug("SessionValidationFilter: white list validation ->  PathInfo: {} ", pathInfo);
177         return excludedUrls.stream().
178                 anyMatch( e -> pathInfo.matches(e));
179     }
180
181     private void cleanResponceFromLeftoverCookies(HttpServletResponse httpResponse, List<Cookie> cookiesList) {
182         for (Cookie cookie:cookiesList){
183             Cookie cleanCookie = AuthenticationCookieUtils.createUpdatedCookie(cookie, null, filterConfiguration);
184             cleanCookie.setMaxAge(0);
185             log.debug("SessionValidationFilter Cleaning Cookie cookie name: {} added to responce", cleanCookie.getName());
186             httpResponse.addCookie(cleanCookie);
187         }
188     }
189
190     @Override
191     public void destroy() {
192
193     }
194 }