Catalog alignment
[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
21 package org.openecomp.sdc.be.filters;
22
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import fj.data.Either;
26 import org.apache.commons.codec.binary.Base64;
27 import org.onap.sdc.security.Passwords;
28 import org.openecomp.sdc.be.components.impl.ConsumerBusinessLogic;
29 import org.openecomp.sdc.be.dao.api.ActionStatus;
30 import org.openecomp.sdc.be.impl.ComponentsUtils;
31 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
32 import org.openecomp.sdc.be.model.ConsumerDefinition;
33 import org.openecomp.sdc.common.api.Constants;
34 import org.openecomp.sdc.common.log.enums.LogLevel;
35 import org.openecomp.sdc.common.log.enums.Severity;
36 import org.openecomp.sdc.common.log.wrappers.Logger;
37 import org.openecomp.sdc.common.log.wrappers.LoggerSdcAudit;
38 import org.openecomp.sdc.exception.ResponseFormat;
39 import org.springframework.web.context.WebApplicationContext;
40
41 import javax.annotation.Priority;
42 import javax.servlet.ServletContext;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.ws.rs.container.ContainerRequestContext;
45 import javax.ws.rs.container.ContainerRequestFilter;
46 import javax.ws.rs.core.Context;
47 import javax.ws.rs.core.Response;
48 import javax.ws.rs.core.Response.ResponseBuilder;
49 import javax.ws.rs.core.Response.Status;
50 import java.io.IOException;
51 import java.io.UnsupportedEncodingException;
52 import java.util.StringTokenizer;
53
54 @Priority(10)
55 public class BasicAuthenticationFilter implements ContainerRequestFilter {
56
57
58         private static LoggerSdcAudit audit = new LoggerSdcAudit(BasicAuthenticationFilter.class);
59     private static final Logger log = Logger.getLogger(BasicAuthenticationFilter.class);
60     private static final String COMPONENT_UTILS_FAILED = "Authentication Filter Failed to get component utils.";
61     private static final String CONSUMER_BL_FAILED = "Authentication Filter Failed to get consumerBL.";
62
63     @Context
64     private HttpServletRequest sr;
65
66     protected Gson gson = new GsonBuilder().setPrettyPrinting().create();
67
68     private String realm = "ASDC";
69
70
71     @Override
72     public void filter(ContainerRequestContext requestContext) throws IOException {
73
74                 audit.startLog(requestContext);
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
83                 if ("Basic".equalsIgnoreCase(basic)) {
84                     try {
85                         String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8");
86                         log.debug("Credentials: {}", credentials);
87                         checkUserCredentials(requestContext, credentials);
88                     } catch (UnsupportedEncodingException e) {
89                         log.error("Authentication Filter Failed Couldn't retrieve authentication", e);
90                         authInvalidHeaderError(requestContext);
91                     }
92                 } else {
93                                         log.error(failedToRetrieveAuthErrorMsg);
94                     authInvalidHeaderError(requestContext);
95                 }
96             } else {
97                                 log.error(failedToRetrieveAuthErrorMsg);
98                 authInvalidHeaderError(requestContext);
99             }
100
101         } else {
102                         log.error("Authentication Filter Failed no authorization header");
103             authRequiredError(requestContext);
104         }
105     }
106
107         private void checkUserCredentials(ContainerRequestContext requestContext, String credentials) {
108         int p = credentials.indexOf(':');
109         if (p != -1) {
110             String userName = credentials.substring(0, p).trim();
111             String password = credentials.substring(p + 1).trim();
112
113             ConsumerBusinessLogic consumerBL = getConsumerBusinessLogic();
114             if (consumerBL == null) {
115                                 abortWith(requestContext, CONSUMER_BL_FAILED, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
116             } else {
117                 Either<ConsumerDefinition, ResponseFormat> result = consumerBL.getConsumer(userName);
118                 validatePassword(requestContext, userName, password, result);
119             }
120         } else {
121                         log.error("Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.");
122             authInvalidHeaderError(requestContext);
123
124         }
125     }
126
127     private void validatePassword(ContainerRequestContext requestContext, String userName, String password, Either<ConsumerDefinition, ResponseFormat> result) {
128         if (result.isRight()) {
129             Integer status = result.right().value().getStatus();
130             if (status == Status.NOT_FOUND.getStatusCode()) {
131                 log.error("Authentication Filter Failed Couldn't find user");
132                 authUserNotFoundError(requestContext, userName);
133             } else {
134                                 abortWith(requestContext, CONSUMER_BL_FAILED, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
135             }
136         } else {
137             ConsumerDefinition consumerCredentials = result.left().value();
138             if (!Passwords.isExpectedPassword(password, consumerCredentials.getConsumerSalt(), consumerCredentials.getConsumerPassword())) {
139                                 log.error("Authentication Filter Failed invalid password");
140                                 authInvalidPasswordError(requestContext, userName);
141             } else {
142                                 authSuccessful(requestContext, userName);
143             }
144         }
145     }
146
147         private void authSuccessful(ContainerRequestContext requestContext, String userName) {
148         ComponentsUtils componentUtils = getComponentsUtils();
149         if (componentUtils == null) {
150                         abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
151         }
152         componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_SUCCESS.toString(), realm);
153     }
154
155         private void authInvalidPasswordError(ContainerRequestContext requestContext, String userName) {
156         ComponentsUtils componentUtils = getComponentsUtils();
157         if (componentUtils == null) {
158                         abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
159         }
160         componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_FAILED_INVALID_PASSWORD.toString(), realm);
161         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
162                 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
163     }
164
165     private void authUserNotFoundError(ContainerRequestContext requestContext, String userName) {
166         ComponentsUtils componentUtils = getComponentsUtils();
167         if (componentUtils == null) {
168                         abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
169         }
170         getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_FAILED_USER_NOT_FOUND.toString(), realm);
171         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
172                 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
173     }
174
175     private void authInvalidHeaderError(ContainerRequestContext requestContext) {
176         ComponentsUtils componentUtils = getComponentsUtils();
177         if (componentUtils == null) {
178                         abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
179         }
180         getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_FAILED_INVALID_AUTHENTICATION_HEADER.toString(), realm);
181         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED_INVALIDE_HEADER);
182                 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
183     }
184
185     private void authRequiredError(ContainerRequestContext requestContext) {
186         ComponentsUtils componentUtils = getComponentsUtils();
187         if (componentUtils == null) {
188                         abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
189         }
190         getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_REQUIRED.toString(), realm);
191         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_REQUIRED);
192                 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, true));
193     }
194
195     private ComponentsUtils getComponentsUtils() {
196         ServletContext context = sr.getSession().getServletContext();
197         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
198         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
199         return webApplicationContext.getBean(ComponentsUtils.class);
200     }
201
202     private ConsumerBusinessLogic getConsumerBusinessLogic() {
203         ServletContext context = sr.getSession().getServletContext();
204         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
205         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
206         return webApplicationContext.getBean(ConsumerBusinessLogic.class);
207     }
208
209     public enum AuthStatus {
210         AUTH_REQUIRED, AUTH_FAILED_USER_NOT_FOUND, AUTH_FAILED_INVALID_PASSWORD, AUTH_FAILED_INVALID_AUTHENTICATION_HEADER, AUTH_SUCCESS
211     }
212
213     protected Response buildErrorResponse(ResponseFormat requestErrorWrapper, boolean addWwwAuthenticationHeader) {
214         ResponseBuilder responseBuilder = Response.status(requestErrorWrapper.getStatus());
215         if (addWwwAuthenticationHeader) {
216             responseBuilder = responseBuilder.header("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
217         }
218                 return responseBuilder.entity(gson.toJson(requestErrorWrapper.getRequestError())).build();
219     }
220
221         private void abortWith(ContainerRequestContext requestContext, String message, Response response) {
222
223                 audit.logEntry(sr.getRemoteAddr(),
224                                 requestContext,
225 //                              response.getStatusInfo(),
226                                 LogLevel.ERROR,
227                                 Severity.WARNING,
228                                 message, null);
229
230                 log.error(message);
231                 audit.clearMyData();
232                 requestContext.abortWith(response);
233         }
234 }