Fix import policy issues
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / filters / BasicAuthenticationFilter.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.filters;
21
22 import com.google.gson.Gson;
23 import com.google.gson.GsonBuilder;
24 import java.io.IOException;
25 import java.nio.charset.StandardCharsets;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.StringTokenizer;
29 import javax.annotation.Priority;
30 import javax.servlet.ServletContext;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.ws.rs.container.ContainerRequestContext;
33 import javax.ws.rs.container.ContainerRequestFilter;
34 import javax.ws.rs.core.Context;
35 import javax.ws.rs.core.Response;
36 import javax.ws.rs.core.Response.ResponseBuilder;
37 import javax.ws.rs.core.Response.Status;
38 import org.apache.commons.codec.binary.Base64;
39 import org.glassfish.jersey.server.ContainerRequest;
40 import org.openecomp.sdc.be.config.Configuration;
41 import org.openecomp.sdc.be.config.ConfigurationManager;
42 import org.openecomp.sdc.be.dao.api.ActionStatus;
43 import org.openecomp.sdc.be.impl.ComponentsUtils;
44 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
45 import org.openecomp.sdc.common.api.Constants;
46 import org.openecomp.sdc.common.log.enums.LogLevel;
47 import org.openecomp.sdc.common.log.enums.Severity;
48 import org.openecomp.sdc.common.log.wrappers.Logger;
49 import org.openecomp.sdc.common.log.wrappers.LoggerSdcAudit;
50 import org.openecomp.sdc.exception.ResponseFormat;
51 import org.springframework.web.context.WebApplicationContext;
52
53 @Priority(10)
54 public class BasicAuthenticationFilter implements ContainerRequestFilter {
55
56     private static final Logger log = Logger.getLogger(BasicAuthenticationFilter.class);
57     private static final String COMPONENT_UTILS_FAILED = "Authentication Filter Failed to get component utils.";
58     private static final ConfigurationManager configurationManager = ConfigurationManager.getConfigurationManager();
59     private static final Configuration.BasicAuthConfig basicAuthConf = configurationManager.getConfiguration().getBasicAuth();
60     private static LoggerSdcAudit audit = new LoggerSdcAudit(BasicAuthenticationFilter.class);
61     protected Gson gson = new GsonBuilder().setPrettyPrinting().create();
62     @Context
63     private HttpServletRequest sr;
64     private String realm = "ASDC";
65
66     @Override
67     public void filter(ContainerRequestContext requestContext) throws IOException {
68         audit.startLog(requestContext);
69         if (!basicAuthConf.isEnabled()) {
70             return;
71         }
72         List<String> excludedUrls = Arrays.asList(basicAuthConf.getExcludedUrls().split(","));
73         if (excludedUrls.contains(((ContainerRequest) requestContext).getRequestUri().getPath())) {
74             return;
75         }
76         String authHeader = requestContext.getHeaderString(Constants.AUTHORIZATION_HEADER);
77         if (authHeader != null) {
78             StringTokenizer st = new StringTokenizer(authHeader);
79             String failedToRetrieveAuthErrorMsg = "Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.";
80             if (st.hasMoreTokens()) {
81                 String basic = st.nextToken();
82                 if ("Basic".equalsIgnoreCase(basic)) {
83                     String credentials = new String(Base64.decodeBase64(st.nextToken()), StandardCharsets.UTF_8);
84                     log.debug("Credentials: {}", credentials);
85                     checkUserCredentials(requestContext, credentials);
86                 } else {
87                     log.error(failedToRetrieveAuthErrorMsg);
88                     authInvalidHeaderError(requestContext);
89                 }
90             } else {
91                 log.error(failedToRetrieveAuthErrorMsg);
92                 authInvalidHeaderError(requestContext);
93             }
94         } else {
95             log.error("Authentication Filter Failed no authorization header");
96             authRequiredError(requestContext);
97         }
98     }
99
100     private void checkUserCredentials(ContainerRequestContext requestContext, String credentials) {
101         int p = credentials.indexOf(':');
102         if (p != -1) {
103             String userName = credentials.substring(0, p).trim();
104             String password = credentials.substring(p + 1).trim();
105             if (!userName.equals(basicAuthConf.getUserName()) || !password.equals(basicAuthConf.getUserPass())) {
106                 log.error("Authentication Failed. Invalid userName or password");
107                 authInvalidPasswordError(requestContext, userName);
108             }
109             authSuccessful(requestContext, userName);
110         } else {
111             log.error("Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.");
112             authInvalidHeaderError(requestContext);
113         }
114     }
115
116     private void authSuccessful(ContainerRequestContext requestContext, String userName) {
117         ComponentsUtils componentUtils = getComponentsUtils();
118         if (componentUtils == null) {
119             abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
120         } else {
121             componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_SUCCESS.toString(), realm);
122         }
123     }
124
125     private void authInvalidPasswordError(ContainerRequestContext requestContext, String userName) {
126         ComponentsUtils componentUtils = getComponentsUtils();
127         if (componentUtils == null) {
128             abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
129         } else {
130             componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_FAILED_INVALID_PASSWORD.toString(), realm);
131             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
132             abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
133         }
134     }
135
136     private void authInvalidHeaderError(ContainerRequestContext requestContext) {
137         ComponentsUtils componentUtils = getComponentsUtils();
138         if (componentUtils == null) {
139             abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
140         }
141         getComponentsUtils()
142             .auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_FAILED_INVALID_AUTHENTICATION_HEADER.toString(), realm);
143         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED_INVALIDE_HEADER);
144         abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
145     }
146
147     private void authRequiredError(ContainerRequestContext requestContext) {
148         ComponentsUtils componentUtils = getComponentsUtils();
149         if (componentUtils == null) {
150             abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
151         }
152         getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_REQUIRED.toString(), realm);
153         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_REQUIRED);
154         abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, true));
155     }
156
157     private ComponentsUtils getComponentsUtils() {
158         ServletContext context = sr.getSession().getServletContext();
159         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context
160             .getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
161         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
162         return webApplicationContext.getBean(ComponentsUtils.class);
163     }
164
165     protected Response buildErrorResponse(ResponseFormat requestErrorWrapper, boolean addWwwAuthenticationHeader) {
166         ResponseBuilder responseBuilder = Response.status(requestErrorWrapper.getStatus());
167         if (addWwwAuthenticationHeader) {
168             responseBuilder = responseBuilder.header("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
169         }
170         return responseBuilder.entity(gson.toJson(requestErrorWrapper.getRequestError())).build();
171     }
172
173     private void abortWith(ContainerRequestContext requestContext, String message, Response response) {
174         audit.logEntry(sr.getRemoteAddr(), requestContext,
175 //                              response.getStatusInfo(),
176             LogLevel.ERROR, Severity.WARNING, message, null);
177         log.error(message);
178         audit.clearMyData();
179         requestContext.abortWith(response);
180     }
181
182     public enum AuthStatus {
183         AUTH_REQUIRED, AUTH_FAILED_USER_NOT_FOUND, AUTH_FAILED_INVALID_PASSWORD, AUTH_FAILED_INVALID_AUTHENTICATION_HEADER, AUTH_SUCCESS
184     }
185 }