VES Collector - certBasicAuth 42/85542/6 1.4.4
authorZlatko Murgoski <zlatko.murgoski@nokia.com>
Wed, 17 Apr 2019 08:10:30 +0000 (10:10 +0200)
committerZlatko Murgoski <zlatko.murgoski@nokia.com>
Thu, 18 Apr 2019 09:04:53 +0000 (11:04 +0200)
https://jira.onap.org/browse/DCAEGEN2-1440

Issue-ID: DCAEGEN2-1440
Change-Id: I7976d03c65e261930533a49a6716fd6161124ad9
Signed-off-by: Zlatko Murgoski <zlatko.murgoski@nokia.com>
src/main/java/org/onap/dcae/common/configuration/CertAuth.java
src/main/java/org/onap/dcae/common/configuration/CertBasicAuth.java
src/main/java/org/onap/dcae/common/configuration/SubjectMatcher.java [moved from src/main/java/org/onap/dcae/common/configuration/CustomFilter.java with 52% similarity]
src/main/java/org/onap/dcae/restapi/ApiAuthInterceptor.java
src/test/java/org/onap/dcae/restapi/ApiAuthInterceptionTest.java

index 481fb5e..6bd924c 100644 (file)
 
 package org.onap.dcae.common.configuration;
 
-import org.onap.dcae.ApplicationException;
 import org.onap.dcae.ApplicationSettings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.web.server.Ssl.ClientAuth;
 import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.core.annotation.Order;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.builders.WebSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
 
 @Configuration
-@Order(0)
-@EnableWebSecurity
-public class CertAuth extends WebSecurityConfigurerAdapter implements AuthMethod {
+public class CertAuth implements AuthMethod {
 
   private static final Logger log = LoggerFactory.getLogger(CertAuth.class);
   private final ConfigurableServletWebServerFactory container;
@@ -49,24 +40,6 @@ public class CertAuth extends WebSecurityConfigurerAdapter implements AuthMethod
     this.properties = properties;
   }
 
-  @Override
-  public void configure(WebSecurity web) {
-    web.ignoring().anyRequest();
-  }
-
-  @Override
-  protected void configure(HttpSecurity http) {
-    try {
-      http.authorizeRequests()
-          .anyRequest().authenticated().and()
-          .addFilterBefore(new CustomFilter(properties), FilterSecurityInterceptor.class);
-
-    } catch (Exception ex) {
-      log.error("Cannot authorize request cause: ",ex);
-      throw new ApplicationException(ex);
-    }
-  }
-
   @Override
   public void configure() {
     SslContextCreator sslContextCreator = new SslContextCreator(properties);
index c9e0af4..38d5ad5 100644 (file)
 
 package org.onap.dcae.common.configuration;
 
-import org.onap.dcae.ApplicationException;
 import org.onap.dcae.ApplicationSettings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.web.server.Ssl.ClientAuth;
 import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.core.annotation.Order;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.builders.WebSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
 
 @Configuration
-@Order(1)
-@EnableWebSecurity
-public class CertBasicAuth extends WebSecurityConfigurerAdapter implements AuthMethod{
+public class CertBasicAuth  implements AuthMethod{
 
   private static final Logger log = LoggerFactory.getLogger(CertAuth.class);
   private final ConfigurableServletWebServerFactory container;
@@ -49,24 +40,6 @@ public class CertBasicAuth extends WebSecurityConfigurerAdapter implements AuthM
     this.properties = properties;
   }
 
-  @Override
-  public void configure(WebSecurity web) {
-    web.ignoring().anyRequest();
-  }
-
-  @Override
-  protected void configure(HttpSecurity http) {
-    try {
-      http.authorizeRequests()
-          .anyRequest().authenticated().and()
-          .addFilterBefore(new CustomFilter(properties), FilterSecurityInterceptor.class);
-
-    } catch (Exception ex) {
-      log.error("Cannot authorize request cause: ",ex);
-      throw new ApplicationException(ex);
-    }
-  }
-
   @Override
   public void configure() {
     SslContextCreator sslContextCreator = new SslContextCreator(properties);
@@ -75,5 +48,4 @@ public class CertBasicAuth extends WebSecurityConfigurerAdapter implements AuthM
     log.info(String.format("Application work in %s mode on %s port.",
         properties.authMethod(), properties.httpsPort()));
   }
-}
-
+}
\ No newline at end of file
@@ -28,47 +28,29 @@ import java.util.Arrays;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
+import org.onap.dcae.ApplicationException;
 import org.onap.dcae.ApplicationSettings;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.filter.GenericFilterBean;
 
-@Configuration
-public class CustomFilter extends GenericFilterBean {
+public class SubjectMatcher {
 
-  private static final String CERTIFICATE_X_509 = "javax.servlet.request.X509Certificate";
-  private static final String MESSAGE = "SubjectDN didn't match with any regexp from %s file like %s";
-  private ApplicationSettings properties;
+  private final ApplicationSettings properties;
+  private final X509Certificate[] cert;
 
-  public CustomFilter(ApplicationSettings properties) {
+  public SubjectMatcher(ApplicationSettings properties, X509Certificate[] cert) {
     this.properties = properties;
+    this.cert = cert;
   }
 
-  @Override
-  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
-      FilterChain filterChain) throws IOException, ServletException {
-
-    X509Certificate[] cert = (X509Certificate[]) servletRequest.getAttribute(CERTIFICATE_X_509);
-
-    if (cert != null) {
-      if (getLines().anyMatch(element -> Pattern.compile(element).matcher(getSubjectDN(cert)).find())) {
-        filterChain.doFilter(servletRequest, servletResponse);
-      } else {
-        setResponse((HttpServletResponse) servletResponse);
-      }
-    } else {
-      filterChain.doFilter(servletRequest, servletResponse);
+  public boolean match(){
+    try {
+      return getLines().anyMatch(element -> Pattern.compile(element).matcher(getSubjectDN(cert)).find());
+    } catch (IOException ex) {
+      throw new ApplicationException("Cannot read file cause: ", ex);
     }
   }
 
-  private void setResponse(HttpServletResponse servletResponse) throws IOException {
-    HttpServletResponse response = servletResponse;
-    response.sendError(HttpServletResponse.SC_FORBIDDEN,
-        String.format(MESSAGE, properties.certSubjectMatcher(), getLines().collect(Collectors.joining(" "))));
+  public boolean isCert() {
+    return cert !=null;
   }
 
   private Stream<String> getLines() throws IOException {
index bb29057..7d3d292 100644 (file)
@@ -21,11 +21,14 @@ package org.onap.dcae.restapi;
 
 import io.vavr.control.Option;
 import java.io.IOException;
+import java.security.cert.X509Certificate;
 import java.util.Base64;
+import java.util.stream.Collectors;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.onap.dcae.ApplicationSettings;
 import org.onap.dcae.common.configuration.AuthMethodType;
+import org.onap.dcae.common.configuration.SubjectMatcher;
 import org.onap.dcaegen2.services.sdk.security.CryptPassword;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -34,11 +37,12 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 final class ApiAuthInterceptor extends HandlerInterceptorAdapter {
 
     private static final Logger LOG = LoggerFactory.getLogger(ApiAuthInterceptor.class);
+    private static final String CERTIFICATE_X_509 = "javax.servlet.request.X509Certificate";
+    private static final String MESSAGE = "SubjectDN didn't match with any regexp from %s";
     private final CryptPassword cryptPassword = new CryptPassword();
     private final ApplicationSettings settings;
     private Logger errorLogger;
 
-
     public ApiAuthInterceptor(ApplicationSettings applicationSettings, Logger errorLogger) {
         this.settings = applicationSettings;
         this.errorLogger = errorLogger;
@@ -48,25 +52,55 @@ final class ApiAuthInterceptor extends HandlerInterceptorAdapter {
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
         throws IOException {
 
-        if(settings.authMethod().equalsIgnoreCase(AuthMethodType.CERT_BASIC_AUTH.value())){
-            if (request.getAttribute("javax.servlet.request.X509Certificate") != null){
-                LOG.info("Request is authorized by certificate ");
-                return true;
-            }
+        SubjectMatcher subjectMatcher = new SubjectMatcher(settings,(X509Certificate[]) request.getAttribute(CERTIFICATE_X_509));
+
+        if(settings.authMethod().equalsIgnoreCase(AuthMethodType.CERT_ONLY.value())){
+            return validateCertRequest(response, subjectMatcher);
+        }
+
+        if(isCertSubject(subjectMatcher)){
+            return true;
+        }
+
+        if (isBasicAuth() ) {
+            return validateBasicHeader(request, response);
+        }
+        return true;
+    }
+
+    private boolean validateBasicHeader(HttpServletRequest request, HttpServletResponse response)
+        throws IOException {
+        String authorizationHeader = request.getHeader("Authorization");
+        if (authorizationHeader == null || !isAuthorized(authorizationHeader)) {
+            response.setStatus(401);
+            errorLogger.error("EVENT_RECEIPT_FAILURE: Unauthorized user");
+            response.getWriter().write(ApiException.UNAUTHORIZED_USER.toJSON().toString());
+            return false;
         }
-        if (isBasicAuth()) {
-            String authorizationHeader = request.getHeader("Authorization");
-            if (authorizationHeader == null || !isAuthorized(authorizationHeader)) {
-                response.setStatus(401);
-                errorLogger.error("EVENT_RECEIPT_FAILURE: Unauthorized user");
-                response.getWriter().write(ApiException.UNAUTHORIZED_USER.toJSON().toString());
-                return false;
-            }
-            LOG.info("Request is authorized by basic auth");
+        LOG.info("Request is authorized by basic auth");
+        return true;
+    }
+
+    private boolean validateCertRequest(HttpServletResponse response, SubjectMatcher subjectMatcher)
+        throws IOException {
+        if (!isCertSubject(subjectMatcher)) {
+            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+            response.getWriter().write(String.format(MESSAGE, settings.certSubjectMatcher()));
+            return false;
         }
+        LOG.info("Cert and subjectDN is valid");
         return true;
     }
 
+    private boolean isCertSubject(SubjectMatcher subjectMatcher) {
+        if(subjectMatcher.isCert() && subjectMatcher.match()){
+            LOG.info("Cert and subjectDN is valid");
+            return true;
+        }
+        LOG.info(String.format(MESSAGE, settings.certSubjectMatcher()));
+        return false;
+    }
+
     private boolean isBasicAuth() {
         return settings.authMethod().equalsIgnoreCase(AuthMethodType.BASIC_AUTH.value())
             || settings.authMethod().equalsIgnoreCase(AuthMethodType.CERT_BASIC_AUTH.value());
index a295046..c0a06a0 100644 (file)
@@ -140,7 +140,7 @@ public class ApiAuthInterceptionTest {
     public void shouldSucceed() throws IOException {
         // given
         final HttpServletRequest request = createRequestWithAuthorizationHeader();
-        when(settings.authMethod()).thenReturn(AuthMethodType.CERT_ONLY.value());
+        when(settings.authMethod()).thenReturn(AuthMethodType.BASIC_AUTH.value());
         when(settings.validAuthorizationCredentials()).thenReturn(
             HashMap.of(USERNAME, "$2a$10$BsZkEynNm/93wbAeeZuxJeu6IHRyQl4XReqDg2BtYOFDhUsz20.3G"));
         when(response.getWriter()).thenReturn(writer);