diff options
author | Alexis de Talhouët <adetalhouet89@gmail.com> | 2019-03-04 21:37:27 -0500 |
---|---|---|
committer | Alexis de Talhouët <adetalhouet89@gmail.com> | 2019-03-05 14:23:52 +0000 |
commit | e4a1f83b13426ce7878e451fe864f9571424d1a7 (patch) | |
tree | d2c2ae18c9231ea79e9e5e4465515ca14a1f492f | |
parent | ee02d9aafb9cf6ff3b045c542fc3a75851b27a93 (diff) |
Add gRPC & REST basic auth support
Change-Id: Iaa187a8288a9c84aa80b596a14e66de10a9b7501
Issue-ID: CCSDK-1055
Signed-off-by: Alexis de Talhouët <adetalhouet89@gmail.com>
16 files changed, 358 insertions, 26 deletions
diff --git a/ms/blueprintsprocessor/application/pom.xml b/ms/blueprintsprocessor/application/pom.xml index 83dc7061f..f42cdfade 100755 --- a/ms/blueprintsprocessor/application/pom.xml +++ b/ms/blueprintsprocessor/application/pom.xml @@ -17,7 +17,8 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.apps.blueprintsprocessor</groupId> @@ -40,6 +41,11 @@ <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <!-- North Bound --> <dependency> <groupId>org.onap.ccsdk.apps.blueprintsprocessor</groupId> diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintGRPCServer.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintGRPCServer.java index 86fdccd4b..3ac1a6e62 100644 --- a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintGRPCServer.java +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintGRPCServer.java @@ -18,6 +18,7 @@ package org.onap.ccsdk.apps.blueprintsprocessor; import io.grpc.Server; import io.grpc.ServerBuilder; +import org.onap.ccsdk.apps.blueprintsprocessor.security.BasicAuthServerInterceptor; import org.onap.ccsdk.apps.blueprintsprocessor.selfservice.api.BluePrintManagementGRPCHandler; import org.onap.ccsdk.apps.blueprintsprocessor.selfservice.api.BluePrintProcessingGRPCHandler; import org.slf4j.Logger; @@ -37,9 +38,10 @@ public class BlueprintGRPCServer implements ApplicationListener<ContextRefreshed @Autowired private BluePrintProcessingGRPCHandler bluePrintProcessingGRPCHandler; - @Autowired private BluePrintManagementGRPCHandler bluePrintManagementGRPCHandler; + @Autowired + private BasicAuthServerInterceptor authInterceptor; @Value("${blueprintsprocessor.grpcPort}") private Integer grpcPort; @@ -49,10 +51,11 @@ public class BlueprintGRPCServer implements ApplicationListener<ContextRefreshed try { log.info("Starting Blueprint Processor GRPC Starting.."); Server server = ServerBuilder - .forPort(grpcPort) - .addService(bluePrintProcessingGRPCHandler) - .addService(bluePrintManagementGRPCHandler) - .build(); + .forPort(grpcPort) + .intercept(authInterceptor) + .addService(bluePrintProcessingGRPCHandler) + .addService(bluePrintManagementGRPCHandler) + .build(); server.start(); log.info("Blueprint Processor GRPC server started and ready to serve on port({})...", server.getPort()); diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintHttpServer.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintHttpServer.java index b00c4627c..9561b78d4 100644 --- a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintHttpServer.java +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintHttpServer.java @@ -16,23 +16,21 @@ package org.onap.ccsdk.apps.blueprintsprocessor; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.server.WebServer; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -@ConditionalOnProperty(name = "blueprintsprocessor.grpcEnable", havingValue = "true") @Component public class BlueprintHttpServer { + private static Logger log = LoggerFactory.getLogger(BlueprintHttpServer.class); @Value("${blueprintsprocessor.httpPort}") diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintProcessorApplication.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintProcessorApplication.java index 241d920a5..3f8dc375c 100644 --- a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintProcessorApplication.java +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/BlueprintProcessorApplication.java @@ -21,7 +21,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-import org.springframework.web.reactive.config.EnableWebFlux;
/**
* BlueprintProcessorApplication
@@ -30,10 +29,10 @@ import org.springframework.web.reactive.config.EnableWebFlux; */
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
-@EnableWebFlux
@ComponentScan(basePackages = {"org.onap.ccsdk.apps.controllerblueprints",
- "org.onap.ccsdk.apps.blueprintsprocessor"})
+ "org.onap.ccsdk.apps.blueprintsprocessor"})
public class BlueprintProcessorApplication {
+
public static void main(String[] args) {
SpringApplication.run(BlueprintProcessorApplication.class, args);
}
diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/WebConfig.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/WebConfig.java index 796a2d794..47c7b7225 100644 --- a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/WebConfig.java +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/WebConfig.java @@ -17,8 +17,17 @@ package org.onap.ccsdk.apps.blueprintsprocessor;
+import org.onap.ccsdk.apps.blueprintsprocessor.security.AuthenticationManager;
+import org.onap.ccsdk.apps.blueprintsprocessor.security.SecurityContextRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.web.reactive.config.*;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+import org.springframework.web.reactive.config.CorsRegistry;
+import org.springframework.web.reactive.config.ResourceHandlerRegistry;
+import org.springframework.web.reactive.config.WebFluxConfigurationSupport;
/**
* WebConfig
@@ -27,21 +36,43 @@ import org.springframework.web.reactive.config.*; */
@Configuration
public class WebConfig extends WebFluxConfigurationSupport {
- @Override
+
+ @Autowired
+ private AuthenticationManager authenticationManager;
+
+ @Autowired
+ private SecurityContextRepository securityContextRepository;
+
+ @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
- .addResourceLocations("classpath:/META-INF/resources/");
+ .addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
- .addResourceLocations("classpath:/META-INF/resources/webjars/");
+ .addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
- .allowedOrigins("*")
- .allowedMethods("*")
- .allowedHeaders("DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range")
- .maxAge(3600);
+ .allowedOrigins("*")
+ .allowedMethods("*")
+ .allowedHeaders("*")
+ .maxAge(3600);
+ }
+
+
+ @Bean
+ public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
+ return http.csrf().disable()
+ .formLogin().disable()
+ .httpBasic().disable()
+ .authenticationManager(authenticationManager)
+ .securityContextRepository(securityContextRepository)
+ .authorizeExchange()
+ .pathMatchers(HttpMethod.OPTIONS).permitAll()
+ .anyExchange().authenticated()
+ .and().build();
+
}
}
diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/AuthenticationManager.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/AuthenticationManager.java new file mode 100644 index 000000000..726be2ce7 --- /dev/null +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/AuthenticationManager.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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.blueprintsprocessor.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.ReactiveAuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import reactor.core.publisher.Mono; + +@Configuration +public class AuthenticationManager implements ReactiveAuthenticationManager { + + @Autowired + private AuthenticationProvider authenticationProvider; + + @Override + public Mono<Authentication> authenticate(Authentication authentication) { + try { + return Mono.just(authenticationProvider.authenticate(authentication)); + } catch (AuthenticationException e) { + return Mono.error(e); + } + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/BasicAuthServerInterceptor.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/BasicAuthServerInterceptor.java new file mode 100644 index 000000000..db0bfce46 --- /dev/null +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/BasicAuthServerInterceptor.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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.blueprintsprocessor.security; + +import com.google.common.base.Strings; +import io.grpc.Metadata; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; +import io.grpc.Status; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +@Component +public class BasicAuthServerInterceptor implements ServerInterceptor { + + private static Logger log = LoggerFactory.getLogger(BasicAuthServerInterceptor.class); + + @Autowired + private AuthenticationManager authenticationManager; + + + @Override + public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall( + ServerCall<ReqT, RespT> call, + Metadata headers, + ServerCallHandler<ReqT, RespT> next) { + String authHeader = headers.get(Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER)); + + if (Strings.isNullOrEmpty(authHeader)) { + throw Status.UNAUTHENTICATED.withDescription("Missing required authentication").asRuntimeException(); + + } + + try { + String[] tokens = decodeBasicAuth(authHeader); + String username = tokens[0]; + + log.info("Basic Authentication Authorization header found for user: {}", username); + + Authentication authRequest = new UsernamePasswordAuthenticationToken(username, tokens[1]); + Authentication authResult = authenticationManager.authenticate(authRequest).block(); + + log.info("Authentication success: {}", authResult); + + SecurityContextHolder.getContext().setAuthentication(authResult); + + } catch (AuthenticationException e) { + SecurityContextHolder.clearContext(); + + log.info("Authentication request failed: {}", e.getMessage()); + + throw Status.UNAUTHENTICATED.withDescription(e.getMessage()).withCause(e).asRuntimeException(); + } + + return next.startCall(call, headers); + } + + private String[] decodeBasicAuth(String authHeader) { + String basicAuth; + try { + basicAuth = new String(Base64.getDecoder().decode(authHeader.substring(6).getBytes(StandardCharsets.UTF_8)), + StandardCharsets.UTF_8); + } catch (IllegalArgumentException | IndexOutOfBoundsException e) { + throw new BadCredentialsException("Failed to decode basic authentication token"); + } + + int delim = basicAuth.indexOf(':'); + if (delim == -1) { + throw new BadCredentialsException("Failed to decode basic authentication token"); + } + + return new String[]{basicAuth.substring(0, delim), basicAuth.substring(delim + 1)}; + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/SecurityConfiguration.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/SecurityConfiguration.java new file mode 100644 index 000000000..7ddc42ccd --- /dev/null +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/SecurityConfiguration.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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.blueprintsprocessor.security; + +import java.util.Collections; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; + +@Configuration +public class SecurityConfiguration { + + @Value("${security.user.name}") + private String username; + + @Value("${security.user.password}") + private String password; + + @Bean + public UserDetailsService inMemoryUserService() { + UserDetails user = new User(username, password, + Collections.singletonList(new SimpleGrantedAuthority("USER"))); + return new InMemoryUserDetailsManager(user); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public AuthenticationProvider inMemoryAuthenticationProvider() { + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + provider.setUserDetailsService(inMemoryUserService()); + return provider; + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/SecurityContextRepository.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/SecurityContextRepository.java new file mode 100644 index 000000000..f9e184a11 --- /dev/null +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/apps/blueprintsprocessor/security/SecurityContextRepository.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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.blueprintsprocessor.security; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextImpl; +import org.springframework.security.web.server.context.ServerSecurityContextRepository; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +@Component +public class SecurityContextRepository implements ServerSecurityContextRepository { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public Mono<Void> save(ServerWebExchange swe, SecurityContext sc) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Mono<SecurityContext> load(ServerWebExchange swe) { + ServerHttpRequest request = swe.getRequest(); + String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION); + if (authHeader != null && authHeader.startsWith("Basic")) { + String[] tokens = decodeBasicAuth(authHeader); + String username = tokens[0]; + String password = tokens[1]; + Authentication auth = new UsernamePasswordAuthenticationToken(username, password); + return this.authenticationManager.authenticate(auth).map(SecurityContextImpl::new); + } else { + return Mono.empty(); + } + } + + private String[] decodeBasicAuth(String authHeader) { + String basicAuth; + try { + basicAuth = new String(Base64.getDecoder().decode(authHeader.substring(6).getBytes(StandardCharsets.UTF_8)), + StandardCharsets.UTF_8); + } catch (IllegalArgumentException | IndexOutOfBoundsException e) { + throw new BadCredentialsException("Failed to decode basic authentication token"); + } + + int delim = basicAuth.indexOf(':'); + if (delim == -1) { + throw new BadCredentialsException("Failed to decode basic authentication token"); + } + + return new String[]{basicAuth.substring(0, delim), basicAuth.substring(delim + 1)}; + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/application/src/main/resources/application.properties b/ms/blueprintsprocessor/application/src/main/resources/application.properties index cfef4f82f..e955c97c3 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application.properties @@ -36,3 +36,6 @@ blueprintsprocessor.db.primary.hibernateDialect=org.hibernate.dialect.MySQL5Inno # Python executor blueprints.processor.functions.python.executor.executionPath=/opt/app/onap/scripts/jython/ccsdk_blueprints blueprints.processor.functions.python.executor.modulePaths=/opt/app/onap/scripts/jython/ccsdk_blueprints,/opt/app/onap/scripts/jython/ccsdk_netconf + +security.user.password: {bcrypt}$2a$10$duaUzVUVW0YPQCSIbGEkQOXwafZGwQ/b32/Ys4R1iwSSawFgz7QNu +security.user.name: ccsdkapps diff --git a/ms/blueprintsprocessor/application/src/test/resources/application.properties b/ms/blueprintsprocessor/application/src/test/resources/application.properties index 2b5bea109..393024516 100644 --- a/ms/blueprintsprocessor/application/src/test/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/test/resources/application.properties @@ -17,6 +17,9 @@ # # Web server config server.port=8080 +blueprintsprocessor.grpcEnable=false +blueprintsprocessor.httpPort=8080 +blueprintsprocessor.grpcPort=9111 # Blueprint Processor File Execution and Handling Properties blueprintsprocessor.blueprintDeployPath=/opt/app/onap/blueprints/deploy blueprintsprocessor.blueprintArchivePath=/opt/app/onap/blueprints/archive @@ -32,3 +35,6 @@ blueprintsprocessor.db.primary.hibernateDialect=org.hibernate.dialect.H2Dialect # Python executor blueprints.processor.functions.python.executor.executionPath=/opt/app/onap/scripts/jython blueprints.processor.functions.python.executor.modulePaths=/opt/app/onap/scripts/jython + +security.user.password: {bcrypt}$2a$10$duaUzVUVW0YPQCSIbGEkQOXwafZGwQ/b32/Ys4R1iwSSawFgz7QNu +security.user.name: ccsdkapps diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml index c05b84ad9..f538a152d 100755 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml @@ -32,6 +32,12 @@ <description>Blueprints Processor Selfservice API</description> <dependencies> + + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-core</artifactId> + </dependency> + <dependency> <groupId>org.onap.ccsdk.apps.components</groupId> <artifactId>proto-definition</artifactId> diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandler.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandler.kt index fb0bc5678..d689187e8 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandler.kt @@ -28,16 +28,18 @@ import org.onap.ccsdk.apps.controllerblueprints.management.api.BluePrintManageme import org.onap.ccsdk.apps.controllerblueprints.management.api.BluePrintManagementOutput import org.onap.ccsdk.apps.controllerblueprints.management.api.BluePrintManagementServiceGrpc import org.slf4j.LoggerFactory +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.stereotype.Service import java.io.File @Service -class BluePrintManagementGRPCHandler(private val bluePrintCoreConfiguration: BluePrintCoreConfiguration, +open class BluePrintManagementGRPCHandler(private val bluePrintCoreConfiguration: BluePrintCoreConfiguration, private val bluePrintCatalogService: BluePrintCatalogService) : BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() { private val log = LoggerFactory.getLogger(BluePrintManagementGRPCHandler::class.java) + @PreAuthorize("hasRole('USER')") override fun uploadBlueprint(request: BluePrintManagementInput, responseObserver: StreamObserver<BluePrintManagementOutput>) { val blueprintName = request.blueprintName val blueprintVersion = request.blueprintVersion @@ -61,6 +63,7 @@ class BluePrintManagementGRPCHandler(private val bluePrintCoreConfiguration: Blu } } + @PreAuthorize("hasRole('USER')") override fun removeBlueprint(request: BluePrintManagementInput, responseObserver: StreamObserver<BluePrintManagementOutput>) { val blueprintName = request.blueprintName val blueprintVersion = request.blueprintVersion diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt index edb1d31dc..aadbec83a 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt @@ -23,14 +23,16 @@ import org.onap.ccsdk.apps.controllerblueprints.processing.api.BluePrintProcessi import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceInput import org.onap.ccsdk.apps.controllerblueprints.processing.api.ExecutionServiceOutput import org.slf4j.LoggerFactory +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.stereotype.Service @Service -class BluePrintProcessingGRPCHandler(private val bluePrintCoreConfiguration: BluePrintCoreConfiguration, +open class BluePrintProcessingGRPCHandler(private val bluePrintCoreConfiguration: BluePrintCoreConfiguration, private val executionServiceHandler: ExecutionServiceHandler) : BluePrintProcessingServiceGrpc.BluePrintProcessingServiceImplBase() { private val log = LoggerFactory.getLogger(BluePrintProcessingGRPCHandler::class.java) + @PreAuthorize("hasRole('USER')") override fun process( responseObserver: StreamObserver<ExecutionServiceOutput>): StreamObserver<ExecutionServiceInput> { diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt index 6477c0678..16f0fa869 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt @@ -23,6 +23,7 @@ import org.onap.ccsdk.apps.blueprintsprocessor.core.api.data.ExecutionServiceOut import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.MediaType import org.springframework.http.codec.multipart.FilePart +import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping @@ -34,7 +35,7 @@ import reactor.core.publisher.Mono @RestController @RequestMapping("/api/v1/execution-service") -class ExecutionServiceController { +open class ExecutionServiceController { @Autowired lateinit var executionServiceHandler: ExecutionServiceHandler @@ -48,6 +49,7 @@ class ExecutionServiceController { @PostMapping(path = ["/upload"], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) @ApiOperation(value = "Upload CBA", notes = "Takes a File and load it in the runtime database") @ResponseBody + @PreAuthorize("hasRole('USER')") fun upload(@RequestPart("file") parts: Mono<FilePart>): Mono<String> { return parts .filter { it is FilePart } @@ -59,6 +61,7 @@ class ExecutionServiceController { @ApiOperation(value = "Resolve Resource Mappings", notes = "Takes the blueprint information and process as per the payload") @ResponseBody + @PreAuthorize("hasRole('USER')") fun process(@RequestBody executionServiceInput: ExecutionServiceInput): ExecutionServiceOutput { if (executionServiceInput.actionIdentifiers.mode == ACTION_MODE_ASYNC) { throw IllegalStateException("Can't process async request through the REST endpoint. Use gRPC for async processing.") diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt index de1201488..b730472e8 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt @@ -24,6 +24,7 @@ import org.onap.ccsdk.apps.blueprintsprocessor.core.api.data.ExecutionServiceInp import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintCatalogService import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.security.SecurityProperties import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest import org.springframework.context.annotation.ComponentScan import org.springframework.core.io.ByteArrayResource @@ -39,7 +40,7 @@ import kotlin.test.assertTrue @RunWith(SpringRunner::class) @WebFluxTest -@ContextConfiguration(classes = [ExecutionServiceHandler::class, BluePrintCoreConfiguration::class, BluePrintCatalogService::class]) +@ContextConfiguration(classes = [ExecutionServiceHandler::class, BluePrintCoreConfiguration::class, BluePrintCatalogService::class, SecurityProperties::class]) @ComponentScan(basePackages = ["org.onap.ccsdk.apps.blueprintsprocessor", "org.onap.ccsdk.apps.controllerblueprints"]) @TestPropertySource(locations = ["classpath:application-test.properties"]) class ExecutionServiceHandlerTest { |