From 55500c3685dbc032c5cb79a727cc588d542e7d15 Mon Sep 17 00:00:00 2001 From: shivasubedi Date: Wed, 23 Jun 2021 16:31:02 +0100 Subject: create quality params in dmi-plugin Issue-ID: CPS-432 Issue-ID: CPS-403 Signed-off-by: tragait Change-Id: I4ada1e4927a3726500396da64c454d9937f95bcf Signed-off-by: shivasubedi --- pom.xml | 154 +++++++++++++++++++-- .../org/onap/cps/ncmp/config/DmiPluginConfig.java | 45 ++++++ .../onap/cps/ncmp/config/WebSecurityConfig.java | 81 +++++++++++ .../ncmp/rest/controller/DmiRestController.java | 7 +- .../org/onap/cps/ncmp/service/DmiServiceImpl.java | 3 + src/main/resources/application.yml | 18 ++- .../rest/controller/ControllerSecuritySpec.groovy | 62 +++++++++ .../rest/controller/DmiRestControllerSpec.groovy | 17 ++- .../cps/ncmp/rest/controller/TestController.java | 34 +++++ src/test/resources/application.yml | 25 ++++ 10 files changed, 429 insertions(+), 17 deletions(-) create mode 100644 src/main/java/org/onap/cps/ncmp/config/DmiPluginConfig.java create mode 100644 src/main/java/org/onap/cps/ncmp/config/WebSecurityConfig.java create mode 100644 src/test/groovy/org/onap/cps/ncmp/rest/controller/ControllerSecuritySpec.groovy create mode 100644 src/test/java/org/onap/cps/ncmp/rest/controller/TestController.java create mode 100644 src/test/resources/application.yml diff --git a/pom.xml b/pom.xml index abed018e..58960120 100644 --- a/pom.xml +++ b/pom.xml @@ -5,9 +5,7 @@ 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. @@ -15,44 +13,43 @@ limitations under the License. ============LICENSE_END========================================================= --> - 4.0.0 - org.onap.oparent oparent 3.2.0 - ONAP - CPS http://www.onap.org/ - org.onap.cps ncmp-dmi-plugin 0.0.1-SNAPSHOT ncmp-dmi-plugin DMI Plugin Service - org.onap.cps.ncmp.Application + 1.1.0-SNAPSHOT + 1.5.0 3.0.8 + 0.8.5 + 0.7 11 - 3.1.0 UTF-8 2.0-M5-groovy-3.0 2.0-M5-groovy-3.0 + 4.1.3 2.5.0 + 3.0.0 2.1.4 1.6.2 3.0.18 - @@ -67,6 +64,11 @@ swagger-annotations ${swagger-annotations-version} + + io.springfox + springfox-boot-starter + ${springfox.version} + org.codehaus.groovy groovy @@ -84,7 +86,6 @@ - org.springframework.boot @@ -125,8 +126,19 @@ swagger-annotations ${swagger-annotations-version} + + io.springfox + springfox-boot-starter + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-actuator + - @@ -209,6 +221,126 @@ + + org.apache.maven.plugins + maven-checkstyle-plugin + + + cps-java-style + + check + + process-sources + + cps-java-style.xml + + ${project.build.sourceDirectory} + + true + true + true + true + warning + true + + + + + + ${project.groupId} + checkstyle + ${cps.version} + + + + + com.github.spotbugs + spotbugs-maven-plugin + ${spotbug.maven.plugin.version} + + + analyze-compile + compile + + check + + + + + + ${project.groupId} + spotbugs + ${cps.version} + compile + + + + + + jp.skypencil.findbugs.slf4j + bug-pattern + ${findbugs.slf4j.version} + + + Max + Low + true + spotbugs-exclude.xml + true + ${basedir}/target/spotbugs + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.maven.plugin.version} + + + org/onap/cps/ncmp/rest/model/* + + + + + default-prepare-agent + + prepare-agent + + + + coverage-check + + check + + + ${basedir}/target/code-coverage/jacoco-ut.exec + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + ${jacoco.minimum.coverage} + + + + + + + + report + verify + + report-aggregate + + + + **/code-coverage/jacoco-ut.exec + + + + + \ No newline at end of file diff --git a/src/main/java/org/onap/cps/ncmp/config/DmiPluginConfig.java b/src/main/java/org/onap/cps/ncmp/config/DmiPluginConfig.java new file mode 100644 index 00000000..427ffe19 --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/config/DmiPluginConfig.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + + +@Configuration +public class DmiPluginConfig { + /** + * Swagger-ui configuration. + */ + @Bean("dmi-plugin-docket") + public Docket api() { + return new Docket(DocumentationType.OAS_30) + .groupName("dmi-plugin-docket") + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build(); + } +} + diff --git a/src/main/java/org/onap/cps/ncmp/config/WebSecurityConfig.java b/src/main/java/org/onap/cps/ncmp/config/WebSecurityConfig.java new file mode 100644 index 00000000..34bfae9d --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/config/WebSecurityConfig.java @@ -0,0 +1,81 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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; + +/** + * Configuration class to implement application security. + * It enforces Basic Authentication access control. + */ +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + private static final String USER_ROLE = "USER"; + + private final String username; + private final String password; + private final String[] permitUris; + + /** + * Constructor. Accepts parameters from configuration. + * + * @param permitUris comma-separated list of uri patterns for endpoints permitted + * @param username username + * @param password password + */ + public WebSecurityConfig( + @Autowired @Value("${security.permit-uri}") final String permitUris, + @Autowired @Value("${security.auth.username}") final String username, + @Autowired @Value("${security.auth.password}") final String password + ) { + super(); + this.permitUris = permitUris.isEmpty() ? new String[] {"/v3/api-docs"} : permitUris.split("\\s{0,9},\\s{0,9}"); + this.username = username; + this.password = password; + } + + @Override + // The team decided to disable default CSRF Spring protection and not implement CSRF tokens validation. + // ncmp is a stateless REST API that is not as vulnerable to CSRF attacks as web applications running in + // web browsers are. ncmp does not manage sessions, each request requires the authentication token in the header. + // See https://docs.spring.io/spring-security/site/docs/5.3.8.RELEASE/reference/html5/#csrf + @SuppressWarnings("squid:S4502") + protected void configure(final HttpSecurity http) throws Exception { + http + .csrf().disable() + .authorizeRequests() + .antMatchers(permitUris).permitAll() + .anyRequest().authenticated() + .and().httpBasic(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(username).password("{noop}" + password).roles(USER_ROLE); + } +} diff --git a/src/main/java/org/onap/cps/ncmp/rest/controller/DmiRestController.java b/src/main/java/org/onap/cps/ncmp/rest/controller/DmiRestController.java index 700ca82c..9507c695 100644 --- a/src/main/java/org/onap/cps/ncmp/rest/controller/DmiRestController.java +++ b/src/main/java/org/onap/cps/ncmp/rest/controller/DmiRestController.java @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.rest.controller; import org.onap.cps.ncmp.rest.api.DmiPluginApi; +import org.onap.cps.ncmp.service.DmiService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; @@ -29,9 +31,12 @@ import org.springframework.web.bind.annotation.RestController; @RestController public class DmiRestController implements DmiPluginApi { + @Autowired + private DmiService dmiService; + @Override public ResponseEntity helloWorld() { - final var helloWorld = "Hello World"; + final var helloWorld = dmiService.getHelloWorld() ; return new ResponseEntity<>(helloWorld, HttpStatus.OK); } diff --git a/src/main/java/org/onap/cps/ncmp/service/DmiServiceImpl.java b/src/main/java/org/onap/cps/ncmp/service/DmiServiceImpl.java index a1cecc3e..b0c140cd 100644 --- a/src/main/java/org/onap/cps/ncmp/service/DmiServiceImpl.java +++ b/src/main/java/org/onap/cps/ncmp/service/DmiServiceImpl.java @@ -19,6 +19,9 @@ package org.onap.cps.ncmp.service; +import org.springframework.stereotype.Service; + +@Service public class DmiServiceImpl implements DmiService { @Override diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 08466681..e506a546 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -26,4 +26,20 @@ security: permit-uri: /manage/health/**,/manage/info,/swagger-ui/**,/swagger-resources/**,/v3/api-docs auth: username: ${CPS_USERNAME} - password: ${CPS_PASSWORD} \ No newline at end of file + password: ${CPS_PASSWORD} + +# Actuator +management: + endpoints: + web: + base-path: /manage + exposure: + include: info,health,loggers + endpoint: + health: + show-details: always + # kubernetes probes: liveness and readiness + probes: + enabled: true + loggers: + enabled: true diff --git a/src/test/groovy/org/onap/cps/ncmp/rest/controller/ControllerSecuritySpec.groovy b/src/test/groovy/org/onap/cps/ncmp/rest/controller/ControllerSecuritySpec.groovy new file mode 100644 index 00000000..796414bd --- /dev/null +++ b/src/test/groovy/org/onap/cps/ncmp/rest/controller/ControllerSecuritySpec.groovy @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.rest.controller + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest +import org.springframework.http.HttpStatus +import org.springframework.test.web.servlet.MockMvc +import spock.lang.Specification + +@WebMvcTest(controllers = TestController.class) +class ControllerSecuritySpec extends Specification { + + @Autowired + MockMvc mvc + + def testEndpoint = '/test' + + def 'Get request with authentication'() { + when: 'request is sent with authentication' + def response = mvc.perform( + get(testEndpoint).header("Authorization", 'Basic Y3BzdXNlcjpjcHNyMGNrcyE=') + ).andReturn().response + then: 'HTTP OK status code is returned' + assert response.status == HttpStatus.OK.value() + } + + def 'Get request without authentication'() { + when: 'request is sent without authentication' + def response = mvc.perform(get(testEndpoint)).andReturn().response + then: 'HTTP Unauthorized status code is returned' + assert response.status == HttpStatus.UNAUTHORIZED.value() + } + + def 'Get request with invalid authentication'() { + when: 'request is sent with invalid authentication' + def response = mvc.perform( + get(testEndpoint).header("Authorization", 'Basic invalid auth') + ).andReturn().response + then: 'HTTP Unauthorized status code is returned' + assert response.status == HttpStatus.UNAUTHORIZED.value() + } +} diff --git a/src/test/groovy/org/onap/cps/ncmp/rest/controller/DmiRestControllerSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/rest/controller/DmiRestControllerSpec.groovy index 5a7db192..268f0a0d 100644 --- a/src/test/groovy/org/onap/cps/ncmp/rest/controller/DmiRestControllerSpec.groovy +++ b/src/test/groovy/org/onap/cps/ncmp/rest/controller/DmiRestControllerSpec.groovy @@ -19,10 +19,12 @@ package org.onap.cps.ncmp.rest.controller -import org.springframework.http.HttpStatus - import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.onap.cps.ncmp.service.DmiService +import org.spockframework.spring.SpringBean +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.http.HttpStatus import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest @@ -30,8 +32,12 @@ import org.springframework.test.web.servlet.MockMvc import spock.lang.Specification @WebMvcTest +@AutoConfigureMockMvc(addFilters = false) class DmiRestControllerSpec extends Specification { + @SpringBean + DmiService mockDmiService = Mock() + @Autowired private MockMvc mvc @@ -43,11 +49,14 @@ class DmiRestControllerSpec extends Specification { def helloWorldEndpoint = "$basePath/v1/helloworld" when: 'get hello world api is invoked' - def response = mvc.perform(get(helloWorldEndpoint)).andReturn().response + def response = mvc.perform( + get(helloWorldEndpoint) + ).andReturn().response then: 'Response Status is OK and contains expected text' response.status == HttpStatus.OK.value() - response.getContentAsString() == 'Hello World' + then: 'the java API was called with the correct parameters' + 1 * mockDmiService.getHelloWorld() } } diff --git a/src/test/java/org/onap/cps/ncmp/rest/controller/TestController.java b/src/test/java/org/onap/cps/ncmp/rest/controller/TestController.java new file mode 100644 index 00000000..a8d87afb --- /dev/null +++ b/src/test/java/org/onap/cps/ncmp/rest/controller/TestController.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.rest.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestController { + + @GetMapping("/test") + ResponseEntity test() { + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 00000000..165d537c --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,25 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Nordix Foundation +# ================================================================================ +# 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. +# +# SPDX-License-Identifier: Apache-2.0 +# ============LICENSE_END========================================================= + +rest: + api: + dmi-base-path: /dmi/api + +security: + auth: + username: cpsuser + password: cpsr0cks! \ No newline at end of file -- cgit 1.2.3-korg