Controller Blueprints Microservice

Add basic authentication for Controllerblueprint MS.

Change-Id: I145e26d6feba873e8d3ed82e4169cbaa425a277e
Issue-ID: CCSDK-590
Signed-off-by: Muthuramalingam, Brinda Santh(bs2796) <bs2796@att.com>
diff --git a/ms/controllerblueprints/application/etc/logback.xml b/ms/controllerblueprints/application/etc/logback.xml
index 0a75e60..6639705 100644
--- a/ms/controllerblueprints/application/etc/logback.xml
+++ b/ms/controllerblueprints/application/etc/logback.xml
@@ -33,6 +33,7 @@
 

     <logger name="org.springframework" level="info"/>

     <logger name="org.springframework.web" level="info"/>

+    <logger name="org.springframework.security.web.authentication" level="warn"/>

     <logger name="org.hibernate" level="error"/>

     <logger name="org.onap.ccsdk.apps" level="info"/>

 

diff --git a/ms/controllerblueprints/application/opt/app/onap/config/application.properties b/ms/controllerblueprints/application/opt/app/onap/config/application.properties
index d281482..e4457d0 100644
--- a/ms/controllerblueprints/application/opt/app/onap/config/application.properties
+++ b/ms/controllerblueprints/application/opt/app/onap/config/application.properties
@@ -18,6 +18,10 @@
 ms_name=org.onap.ccsdk.apps.controllerblueprints
 appVersion=1.0.0
 
+# Basic Authentication
+basic-auth.user-name=ccsdkapps
+basic-auth.hashed-pwd=$2a$10$MJxhNiOAffxbyrV9.rrOUewP9Q/ASg5Nit2cmP.yBaXGsVXo8BW3y
+
 #logging.pattern.console=%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr($ threadId: {PID:- }){magenta} %clr(---){faint} %clr([ hostname: %X{hostname} serviceName: %X{serviceName} version: %X{version} transactionId: %X{transactionId} requestTimeStamp: %X{requestTimestamp}  responseTimeStamp: %X{responseTimestamp} duration: %X{duration}]){yellow} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex
 
 logging.level.org.springframework.web=INFO
diff --git a/ms/controllerblueprints/application/pom.xml b/ms/controllerblueprints/application/pom.xml
index 24f4deb..9834924 100644
--- a/ms/controllerblueprints/application/pom.xml
+++ b/ms/controllerblueprints/application/pom.xml
@@ -55,6 +55,10 @@
         </dependency>

         <dependency>

             <groupId>org.springframework.boot</groupId>

+            <artifactId>spring-boot-starter-security</artifactId>

+        </dependency>

+        <dependency>

+            <groupId>org.springframework.boot</groupId>

             <artifactId>spring-boot-starter-actuator</artifactId>

         </dependency>

         <dependency>

@@ -68,6 +72,11 @@
             <scope>test</scope>

         </dependency>

         <dependency>

+            <groupId>org.springframework.security</groupId>

+            <artifactId>spring-security-test</artifactId>

+            <scope>test</scope>

+        </dependency>

+        <dependency>

             <groupId>org.jetbrains.kotlin</groupId>

             <artifactId>kotlin-test</artifactId>

             <scope>test</scope>

diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java
index 6e9dcd7..78706d5 100644
--- a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java
+++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java
@@ -23,13 +23,19 @@
 import org.springframework.http.HttpStatus;

 import org.springframework.http.ResponseEntity;

 import org.springframework.http.converter.HttpMessageNotReadableException;

+import org.springframework.security.authentication.BadCredentialsException;

+import org.springframework.security.web.csrf.InvalidCsrfTokenException;

 import org.springframework.web.HttpRequestMethodNotSupportedException;

 import org.springframework.web.bind.MethodArgumentNotValidException;

 import org.springframework.web.bind.annotation.ControllerAdvice;

 import org.springframework.web.bind.annotation.ExceptionHandler;

+import org.springframework.web.bind.annotation.ResponseStatus;

 import org.springframework.web.bind.annotation.RestController;

 import org.springframework.web.context.request.WebRequest;

 

+import javax.naming.AuthenticationException;

+import java.nio.file.AccessDeniedException;

+

 @ControllerAdvice

 @RestController

 @SuppressWarnings("unused")

@@ -43,6 +49,14 @@
         return new ResponseEntity<>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);

     }

 

+    @ExceptionHandler({InvalidCsrfTokenException.class, AuthenticationException.class, BadCredentialsException.class, AccessDeniedException.class})

+    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)

+    public final ResponseEntity<ErrorMessage> handleAuthenticationRequest(Exception ex, WebRequest request) {

+        log.error("Authentication Exception", ex);

+        ErrorMessage exceptionResponse = new ErrorMessage(ex.getMessage(), HttpStatus.UNAUTHORIZED.value(), ex.getLocalizedMessage());

+        return new ResponseEntity<>(exceptionResponse, HttpStatus.UNAUTHORIZED);

+    }

+

     @ExceptionHandler({HttpMessageNotReadableException.class, MethodArgumentNotValidException.class,

             HttpRequestMethodNotSupportedException.class})

     public final ResponseEntity<ErrorMessage> handleBadRequest(Exception ex, WebRequest request) {

diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java
index fbef55f..4476117 100644
--- a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java
+++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java
@@ -25,6 +25,8 @@
 import org.slf4j.LoggerFactory;

 import org.slf4j.MDC;

 import org.springframework.beans.factory.annotation.Value;

+import org.springframework.core.Ordered;

+import org.springframework.core.annotation.Order;

 import org.springframework.stereotype.Component;

 

 import javax.servlet.*;

@@ -40,6 +42,7 @@
  */

 @Component

 @WebFilter(asyncSupported = true, urlPatterns = {"/*"})

+@Order(Ordered.HIGHEST_PRECEDENCE)

 @SuppressWarnings("unused")

 public class ApplicationLoggingFilter implements Filter {

     private static Logger log = LoggerFactory.getLogger(ApplicationLoggingFilter.class);

diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/security/ApplicationBasicAuthenticationEntryPoint.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/security/ApplicationBasicAuthenticationEntryPoint.java
new file mode 100644
index 0000000..e3df3a6
--- /dev/null
+++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/security/ApplicationBasicAuthenticationEntryPoint.java
@@ -0,0 +1,43 @@
+/*

+ *  Copyright © 2017-2018 AT&T Intellectual Property.

+ *

+ *  Licensed under the Apache License, Version 2.0 (the "License");

+ *  you may not use this file except in compliance with the License.

+ *  You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ *  Unless required by applicable law or agreed to in writing, software

+ *  distributed under the License is distributed on an "AS IS" BASIS,

+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ *  See the License for the specific language governing permissions and

+ *  limitations under the License.

+ */

+

+package org.onap.ccsdk.apps.controllerblueprints.security;

+

+import org.springframework.security.core.AuthenticationException;

+import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;

+import org.springframework.stereotype.Component;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import java.io.IOException;

+

+@Component

+public class ApplicationBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {

+

+    @Override

+    public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException)

+            throws IOException {

+        response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\"");

+        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");

+    }

+

+    @Override

+    public void afterPropertiesSet() throws Exception {

+        setRealmName("CCSDK-APPS");

+        super.afterPropertiesSet();

+    }

+

+}
\ No newline at end of file
diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/security/ApplicationSecurityConfigurerAdapter.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/security/ApplicationSecurityConfigurerAdapter.java
new file mode 100644
index 0000000..3a39d78
--- /dev/null
+++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/security/ApplicationSecurityConfigurerAdapter.java
@@ -0,0 +1,72 @@
+/*

+ *  Copyright © 2017-2018 AT&T Intellectual Property.

+ *

+ *  Licensed under the Apache License, Version 2.0 (the "License");

+ *  you may not use this file except in compliance with the License.

+ *  You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ *  Unless required by applicable law or agreed to in writing, software

+ *  distributed under the License is distributed on an "AS IS" BASIS,

+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ *  See the License for the specific language governing permissions and

+ *  limitations under the License.

+ */

+

+package org.onap.ccsdk.apps.controllerblueprints.security;

+

+import com.att.eelf.configuration.EELFLogger;

+import com.att.eelf.configuration.EELFManager;

+import org.springframework.beans.factory.annotation.Autowired;

+import org.springframework.beans.factory.annotation.Value;

+import org.springframework.context.annotation.Bean;

+import org.springframework.context.annotation.Configuration;

+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

+import org.springframework.security.config.annotation.web.builders.HttpSecurity;

+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

+import org.springframework.security.crypto.password.PasswordEncoder;

+

+@SuppressWarnings("unused")

+@Configuration

+@EnableWebSecurity

+public class ApplicationSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

+

+    @Value("${basic-auth.user-name}")

+    private String userName;

+

+    @Value("${basic-auth.hashed-pwd}")

+    private String userHashedPassword;

+

+    private static EELFLogger log = EELFManager.getInstance().getLogger(ApplicationSecurityConfigurerAdapter.class);

+

+    @Autowired

+    private ApplicationBasicAuthenticationEntryPoint authenticationEntryPoint;

+

+    @Autowired

+    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

+        log.info("User Id {} and hashed pwd : {}", userName, userHashedPassword);

+        auth.inMemoryAuthentication()

+                .withUser(userName).password(userHashedPassword)

+                .authorities("ROLE_USER");

+    }

+

+    @Override

+    protected void configure(HttpSecurity http) throws Exception {

+        http.authorizeRequests()

+                .antMatchers("/actuator/health").permitAll()

+                .antMatchers("/**").authenticated()

+                .and()

+                .httpBasic()

+                .authenticationEntryPoint(authenticationEntryPoint);

+

+        http.csrf().disable();

+    }

+

+    @Bean

+    public PasswordEncoder passwordEncoder() {

+        return new BCryptPasswordEncoder();

+    }

+}
\ No newline at end of file
diff --git a/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplicationTest.java b/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplicationTest.java
index 61b5c50..7a5f952 100644
--- a/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplicationTest.java
+++ b/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplicationTest.java
@@ -1,6 +1,6 @@
 /*

  * Copyright © 2017-2018 AT&T Intellectual Property.

- * Modifications Copyright © 2018 IBM.

+ *

  * Licensed under the Apache License, Version 2.0 (the "License");

  * you may not use this file except in compliance with the License.

  * You may obtain a copy of the License at

@@ -16,8 +16,6 @@
 

 package org.onap.ccsdk.apps.controllerblueprints;

 

-import static org.assertj.core.api.Assertions.assertThat;

-

 import org.junit.Assert;

 import org.junit.Before;

 import org.junit.Test;

@@ -27,56 +25,40 @@
 import org.springframework.boot.test.context.SpringBootTest;

 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;

 import org.springframework.boot.test.web.client.TestRestTemplate;

-import org.springframework.http.HttpEntity;

-import org.springframework.http.HttpHeaders;

-import org.springframework.http.HttpMethod;

-import org.springframework.http.HttpStatus;

-import org.springframework.http.MediaType;

-import org.springframework.http.ResponseEntity;

+import org.springframework.http.*;

+import org.springframework.http.client.support.BasicAuthorizationInterceptor;

 import org.springframework.test.context.junit4.SpringRunner;

 

-import com.att.eelf.configuration.EELFLogger;

-import com.att.eelf.configuration.EELFManager;

+import static org.assertj.core.api.Assertions.assertThat;

 

 @RunWith(SpringRunner.class)

 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

 public class ControllerBluprintsApplicationTest {

-    private static EELFLogger log = EELFManager.getInstance().getLogger(ControllerBluprintsApplicationTest.class);

-

     @Autowired

     private TestRestTemplate restTemplate;

-    private HttpHeaders headers;

-    private ResponseEntity<ConfigModel> entity;

 

     @Before

     public void setUp(){

-        headers = new HttpHeaders();

-        headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

-        entity = this.restTemplate

-                .exchange("/api/v1/config-model/1", HttpMethod.GET, new HttpEntity<>(headers),ConfigModel.class);

-        

+        BasicAuthorizationInterceptor bai = new BasicAuthorizationInterceptor("ccsdkapps", "ccsdkapps");

+        this.restTemplate.getRestTemplate().getInterceptors().add(bai);

     }

 

     @Test

     public void testConfigModel() {

-

         HttpHeaders headers = new HttpHeaders();

         headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

         ResponseEntity<ConfigModel> entity = this.restTemplate

                 .exchange("/api/v1/config-model/1", HttpMethod.GET, new HttpEntity<>(headers),ConfigModel.class);

-

         assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);

         Assert.assertNotNull("failed to get response Config model",entity.getBody());

     }

 

     @Test

     public void testConfigModelFailure() {

-

         HttpHeaders headers = new HttpHeaders();

         headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

         ResponseEntity<ConfigModel> entity = this.restTemplate

                 .exchange("/api/v1/config-model-not-found/1", HttpMethod.GET, new HttpEntity<>(headers),ConfigModel.class);

-

         assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);

         Assert.assertNotNull("failed to get response Config model",entity.getBody());

     }

diff --git a/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java b/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java
index 9445e1d..995644f 100644
--- a/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java
+++ b/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java
@@ -16,21 +16,34 @@
 

 package org.onap.ccsdk.apps.controllerblueprints;

 

+import com.att.eelf.configuration.EELFLogger;

+import com.att.eelf.configuration.EELFManager;

 import org.apache.commons.lang3.StringUtils;

 import org.junit.Assert;

 import org.junit.Test;

+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

+

 /**

  * VersionSplitTest

  *

  * @author Brinda Santh

  */

 public class VersionSplitTest {

+    private static EELFLogger log = EELFManager.getInstance().getLogger(VersionSplitTest.class);

 

     @Test

     public void testVersionSplit() {

         String version = "1.03.04";

         String[] tokens = StringUtils.split(version, '.');

         Assert.assertNotNull("failed to tokenize", tokens);

-        Assert.assertEquals("failed to three token ", 3, tokens.length );

+        Assert.assertEquals("failed to three token ", 3, tokens.length);

+    }

+

+    @Test

+    public void encodeTest() {

+        String name = "ccsdkapps";

+        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();

+        String encodedValue = bCryptPasswordEncoder.encode(name);

+        Assert.assertTrue("Failed to match", bCryptPasswordEncoder.matches(name, encodedValue));

     }

 }
\ No newline at end of file
diff --git a/ms/controllerblueprints/application/src/test/resources/application.properties b/ms/controllerblueprints/application/src/test/resources/application.properties
index 5c6acf9..e812da5 100644
--- a/ms/controllerblueprints/application/src/test/resources/application.properties
+++ b/ms/controllerblueprints/application/src/test/resources/application.properties
@@ -20,6 +20,10 @@
 ms_name=org.onap.ccsdk.apps.controllerblueprints

 appVersion=1.0.0

 

+# Basic Authentication

+basic-auth.user-name=ccsdkapps

+basic-auth.hashed-pwd=$2a$10$MJxhNiOAffxbyrV9.rrOUewP9Q/ASg5Nit2cmP.yBaXGsVXo8BW3y

+

 #To Remove Null in JSON API Response

 spring.jackson.default-property-inclusion=non_null