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=========================================================
21 package org.onap.aai.aaf.filters;
23 import java.io.IOException;
24 import java.security.cert.X509Certificate;
27 import javax.security.auth.x500.X500Principal;
28 import javax.servlet.FilterChain;
29 import javax.servlet.ServletException;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
33 import org.onap.aai.aaf.auth.AAIAuthCore;
34 import org.onap.aai.aaf.auth.CertUtil;
35 import org.onap.aai.aaf.auth.ResponseFormatter;
36 import org.onap.aai.exceptions.AAIException;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.springframework.beans.factory.annotation.Autowired;
40 import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
41 import org.springframework.context.annotation.Profile;
42 import org.springframework.core.env.Environment;
43 import org.springframework.stereotype.Component;
46 @Profile("two-way-ssl")
47 public class TwoWaySslAuthorization extends OrderedRequestContextFilter {
49 private static final Logger LOGGER = LoggerFactory.getLogger(TwoWaySslAuthorization.class);
51 public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
53 public static final String MERGE_PATCH = "MERGE_PATCH";
56 private Environment environment;
59 private AAIAuthCore aaiAuthCore;
62 private CadiProps cadiProps;
64 public TwoWaySslAuthorization() {
65 this.setOrder(FilterPriority.TWO_WAY_SSL_AUTH.getPriority());
69 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
70 throws IOException, ServletException {
72 String uri = request.getRequestURI();
73 String httpMethod = getHttpMethod(request);
75 Optional<String> authUser = getUser(request);
77 if (authUser.isPresent()) {
78 Properties cadiProperties = cadiProps.getCadiProperties();
80 String issuer = CertUtil.getCertIssuer(request);
81 if (issuer == null || issuer.isEmpty()) {
82 AAIException aaie = new AAIException("AAI_9107");
83 ResponseFormatter.errorResponse(aaie, request, response);
86 issuer = issuer.replaceAll("\\s+", "").toUpperCase();
88 List<String> cadiConfiguredIssuers = CertUtil.getCadiCertIssuers(cadiProperties);
89 boolean isAafAuthProfileActive = this.isAafAuthProfileActive();
90 if ((!isAafAuthProfileActive) || (!cadiConfiguredIssuers.contains(issuer))) {
92 this.authorize(uri, httpMethod, authUser.get(), this.getHaProxyUser(request), issuer);
93 } catch (AAIException e) {
94 ResponseFormatter.errorResponse(e, request, response);
99 AAIException aaie = new AAIException("AAI_9107");
100 ResponseFormatter.errorResponse(aaie, request, response);
103 filterChain.doFilter(request, response);
106 private String getHttpMethod(HttpServletRequest request) {
107 String httpMethod = request.getMethod();
108 if ("POST".equalsIgnoreCase(httpMethod) && "PATCH".equals(request.getHeader(HTTP_METHOD_OVERRIDE))) {
109 httpMethod = MERGE_PATCH;
111 if (httpMethod.equalsIgnoreCase(MERGE_PATCH) || "patch".equalsIgnoreCase(httpMethod)) {
117 private Optional<String> getUser(HttpServletRequest hsr) {
118 String authUser = null;
119 if (hsr.getAttribute("javax.servlet.request.cipher_suite") != null) {
120 X509Certificate[] certChain = (X509Certificate[]) hsr.getAttribute("javax.servlet.request.X509Certificate");
123 * If the certificate is null or the certificate chain length is zero Then
124 * retrieve the authorization in the request header Authorization Check that it
125 * is not null and that it starts with Basic and then strip the basic portion to
126 * get the base64 credentials Check if this is contained in the AAIBasicAuth
127 * Singleton class If it is, retrieve the username associated with that
128 * credentials and set to authUser Otherwise, get the principal from certificate
129 * and use that authUser
132 if (certChain == null || certChain.length == 0) {
134 String authorization = hsr.getHeader("Authorization");
136 if (authorization != null && authorization.startsWith("Basic ")) {
137 authUser = authorization.replace("Basic ", "");
141 X509Certificate clientCert = certChain[0];
142 X500Principal subjectDN = clientCert.getSubjectX500Principal();
143 authUser = subjectDN.toString().toLowerCase();
147 return Optional.ofNullable(authUser);
150 private String getHaProxyUser(HttpServletRequest hsr) {
152 if (Objects.isNull(hsr.getHeader("X-AAI-SSL-Client-CN")) || 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)
171 throws AAIException {
172 if (!aaiAuthCore.authorize(authUser, uri, httpMethod, haProxyUser, issuer)) {
173 throw new AAIException("AAI_9101", "Request on " + httpMethod + " " + uri + " status is not OK");
177 private boolean isAafAuthProfileActive() {
178 String[] profiles = environment.getActiveProfiles();
179 if (profiles != null) {
180 if (Arrays.stream(profiles).anyMatch(env -> (env.equalsIgnoreCase(AafProfiles.AAF_CERT_AUTHENTICATION)))) {