2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2019 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.onap.aai.aaf.filters;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.onap.aai.aaf.auth.AAIAuthCore;
25 import org.onap.aai.aaf.auth.CertUtil;
26 import org.onap.aai.aaf.auth.ResponseFormatter;
27 import org.onap.aai.exceptions.AAIException;
28 import org.springframework.beans.factory.annotation.Autowired;
29 import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
30 import org.springframework.context.annotation.Profile;
31 import org.springframework.core.env.Environment;
32 import org.springframework.stereotype.Component;
34 import javax.security.auth.x500.X500Principal;
35 import javax.servlet.FilterChain;
36 import javax.servlet.ServletException;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39 import java.io.IOException;
40 import java.security.cert.X509Certificate;
44 @Profile("two-way-ssl")
45 public class TwoWaySslAuthorization extends OrderedRequestContextFilter {
47 private static final Logger LOGGER = LoggerFactory.getLogger(TwoWaySslAuthorization.class);
49 public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
51 public static final String MERGE_PATCH = "MERGE_PATCH";
54 private Environment environment;
57 private AAIAuthCore aaiAuthCore;
60 private CadiProps cadiProps;
62 public TwoWaySslAuthorization(){
63 this.setOrder(FilterPriority.TWO_WAY_SSL_AUTH.getPriority());
67 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
69 String uri = request.getRequestURI();
70 String httpMethod = getHttpMethod(request);
72 Optional<String> authUser = getUser(request);
74 if (authUser.isPresent()) {
75 Properties cadiProperties = cadiProps.getCadiProperties();
77 String issuer = CertUtil.getCertIssuer(request);
78 if (issuer == null || issuer.isEmpty()) {
79 AAIException aaie = new AAIException("AAI_9107");
80 ResponseFormatter.errorResponse(aaie, request, response);
83 issuer = issuer.replaceAll("\\s+","").toUpperCase();
85 List<String> cadiConfiguredIssuers = CertUtil.getCadiCertIssuers(cadiProperties);
86 boolean isAafAuthProfileActive = this.isAafAuthProfileActive();
87 if ((!isAafAuthProfileActive) || (!cadiConfiguredIssuers.contains(issuer)) ) {
89 this.authorize(uri, httpMethod, authUser.get(), this.getHaProxyUser(request), issuer);
90 } catch (AAIException e) {
91 ResponseFormatter.errorResponse(e, request, response);
96 AAIException aaie = new AAIException("AAI_9107");
97 ResponseFormatter.errorResponse(aaie, request, response);
100 filterChain.doFilter(request, response);
104 private String getHttpMethod(HttpServletRequest request) {
105 String httpMethod = request.getMethod();
106 if ("POST".equalsIgnoreCase(httpMethod)
107 && "PATCH".equals(request.getHeader(HTTP_METHOD_OVERRIDE))) {
108 httpMethod = MERGE_PATCH;
110 if (httpMethod.equalsIgnoreCase(MERGE_PATCH) || "patch".equalsIgnoreCase(httpMethod)) {
116 private Optional<String> getUser(HttpServletRequest hsr) {
117 String authUser = null;
118 if (hsr.getAttribute("javax.servlet.request.cipher_suite") != null) {
119 X509Certificate[] certChain = (X509Certificate[]) hsr.getAttribute("javax.servlet.request.X509Certificate");
122 * If the certificate is null or the certificate chain length is zero Then
123 * retrieve the authorization in the request header Authorization Check that it
124 * is not null and that it starts with Basic and then strip the basic portion to
125 * get the base64 credentials Check if this is contained in the AAIBasicAuth
126 * Singleton class If it is, retrieve the username associated with that
127 * credentials and set to authUser Otherwise, get the principal from certificate
128 * and use that authUser
131 if (certChain == null || certChain.length == 0) {
133 String authorization = hsr.getHeader("Authorization");
135 if (authorization != null && authorization.startsWith("Basic ")) {
136 authUser = authorization.replace("Basic ", "");
140 X509Certificate clientCert = certChain[0];
141 X500Principal subjectDN = clientCert.getSubjectX500Principal();
142 authUser = subjectDN.toString().toLowerCase();
146 return Optional.ofNullable(authUser);
149 private String getHaProxyUser(HttpServletRequest hsr) {
151 if (Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-CN"))
152 || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-OU"))
153 || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-O"))
154 || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-L"))
155 || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-ST"))
156 || Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-C"))) {
159 haProxyUser = String.format("CN=%s, OU=%s, O=\"%s\", L=%s, ST=%s, C=%s",
160 Objects.toString(hsr.getHeader("X-AAI-SSL-Client-CN"), ""),
161 Objects.toString(hsr.getHeader("X-AAI-SSL-Client-OU"), ""),
162 Objects.toString(hsr.getHeader("X-AAI-SSL-Client-O"), ""),
163 Objects.toString(hsr.getHeader("X-AAI-SSL-Client-L"), ""),
164 Objects.toString(hsr.getHeader("X-AAI-SSL-Client-ST"), ""),
165 Objects.toString(hsr.getHeader("X-AAI-SSL-Client-C"), "")).toLowerCase();
170 private void authorize(String uri, String httpMethod, String authUser, String haProxyUser, String issuer) throws AAIException {
171 if (!aaiAuthCore.authorize(authUser, uri, httpMethod, haProxyUser, issuer)) {
172 throw new AAIException("AAI_9101", "Request on " + httpMethod + " " + uri + " status is not OK");
176 private boolean isAafAuthProfileActive() {
177 String[] profiles = environment.getActiveProfiles();
178 if (profiles != null) {
179 if (Arrays.stream(profiles).anyMatch(
180 env -> (env.equalsIgnoreCase(AafProfiles.AAF_CERT_AUTHENTICATION)))) {