diff options
author | ToineSiebelink <toine.siebelink@est.tech> | 2024-08-27 14:56:44 +0100 |
---|---|---|
committer | ToineSiebelink <toine.siebelink@est.tech> | 2024-08-29 09:31:04 +0100 |
commit | a05ca3d3152de44ac3078e2455834dedb5789b1b (patch) | |
tree | 07b2346b58b27394827766cb28ff24e9d70df25f /integration-test | |
parent | 0ae8299c8a4c811cc5bc001a8531f367687f0678 (diff) |
Invoke Policy Executor and handle not-allowed response
- Execute Policy Executor REST request
- Act (and log) on response from Policy Executor
- Add dispatcher(mock) in integration test FWK
- Add integration test for allow/non allowed and no authorization use cases
- disabled PolicyExecution feature by default (only enabled for testware)
Issue-ID: CPS-2247
Change-Id: I111ba9ba89cc91649b63b20f88414aa33721dbeb
Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Signed-off-by: mpriyank <priyank.maheshwari@est.tech>
Diffstat (limited to 'integration-test')
5 files changed, 173 insertions, 9 deletions
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy index 5e46e95a0c..bd53c4ea13 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy @@ -46,6 +46,7 @@ import org.onap.cps.spi.utils.SessionManager import org.onap.cps.utils.ContentType import org.onap.cps.utils.JsonObjectMapper import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc @@ -125,12 +126,19 @@ abstract class CpsIntegrationSpecBase extends Specification { @Autowired AlternateIdMatcher alternateIdMatcher + + @Value('${ncmp.policy-executor.server.port:8080}') + private String policyServerPort; + MockWebServer mockDmiServer1 = new MockWebServer() MockWebServer mockDmiServer2 = new MockWebServer() + MockWebServer mockPolicyServer = new MockWebServer() DmiDispatcher dmiDispatcher1 = new DmiDispatcher() DmiDispatcher dmiDispatcher2 = new DmiDispatcher() + PolicyDispatcher policyDispatcher = new PolicyDispatcher(); + def DMI1_URL = null def DMI2_URL = null @@ -155,13 +163,18 @@ abstract class CpsIntegrationSpecBase extends Specification { mockDmiServer2.setDispatcher(dmiDispatcher2) mockDmiServer2.start() + mockPolicyServer.setDispatcher(policyDispatcher) + mockPolicyServer.start(Integer.valueOf(policyServerPort)) + DMI1_URL = String.format("http://%s:%s", mockDmiServer1.getHostName(), mockDmiServer1.getPort()) DMI2_URL = String.format("http://%s:%s", mockDmiServer2.getHostName(), mockDmiServer2.getPort()) + } def cleanup() { mockDmiServer1.shutdown() mockDmiServer2.shutdown() + mockPolicyServer.shutdown() } def static readResourceDataFile(filename) { diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy index fcc23db782..35a7b6a7c2 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy @@ -20,18 +20,18 @@ package org.onap.cps.integration.base -import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile - import groovy.json.JsonSlurper -import java.util.regex.Matcher import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest -import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteRequest import org.springframework.http.HttpHeaders import org.springframework.http.HttpStatus import org.springframework.http.MediaType +import java.util.regex.Matcher + +import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile + /** * This class simulates responses from the DMI server in NCMP integration tests. * @@ -117,32 +117,32 @@ class DmiDispatcher extends Dispatcher { return mockResponseWithBody(HttpStatus.OK, response) } - private getModuleReferencesResponse(cmHandleId) { + def getModuleReferencesResponse(cmHandleId) { def moduleReferences = '{"schemas":[' + getModuleNamesForCmHandle(cmHandleId).collect { MODULE_REFERENCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it) }.join(',') + ']}' return mockResponseWithBody(HttpStatus.OK, moduleReferences) } - private getModuleResourcesResponse(cmHandleId) { + def getModuleResourcesResponse(cmHandleId) { def moduleResources = '[' + getModuleNamesForCmHandle(cmHandleId).collect { MODULE_RESOURCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it) }.join(',') + ']' return mockResponseWithBody(HttpStatus.OK, moduleResources) } - private getModuleNamesForCmHandle(cmHandleId) { + def getModuleNamesForCmHandle(cmHandleId) { if (!moduleNamesPerCmHandleId.containsKey(cmHandleId)) { throw new IllegalArgumentException('Mock DMI has no modules configured for ' + cmHandleId) } return moduleNamesPerCmHandleId.get(cmHandleId) } - private static mockResponse(status) { + def static mockResponse(status) { return new MockResponse().setResponseCode(status.value()) } - private static mockResponseWithBody(status, responseBody) { + def static mockResponseWithBody(status, responseBody) { return new MockResponse() .setResponseCode(status.value()) .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy new file mode 100644 index 0000000000..27e7563e61 --- /dev/null +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.integration.base + + +import okhttp3.mockwebserver.Dispatcher +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.RecordedRequest +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper + +/** + * This class simulates responses from the Policy Execution server in NCMP integration tests. + */ +class PolicyDispatcher extends Dispatcher { + + def objectMapper = new ObjectMapper() + def expectedAuthorizationToken = 'ABC' + def allowAll = true; // Prevents legacy test being affected + + @Override + MockResponse dispatch(RecordedRequest recordedRequest) { + + if (!allowAll && !recordedRequest.getHeader('Authorization').contains(expectedAuthorizationToken)) { + return new MockResponse().setResponseCode(401) + } + + if (recordedRequest.path != '/v1/execute') { + return new MockResponse().setResponseCode(400) + } + + def body = objectMapper.readValue(recordedRequest.getBody().readUtf8(), Map.class) + def targetIdentifier = body.get('requests').get(0).get('data').get('targetIdentifier') + def responseAsMap = [:] + responseAsMap.put('decisionId',1) + if (allowAll || targetIdentifier == 'fdn1') { + responseAsMap.put('decision','allow') + responseAsMap.put('message','') + } else { + responseAsMap.put('decision','deny') + responseAsMap.put('message','I only like fdn1') + } + def responseAsString = objectMapper.writeValueAsString(responseAsMap) + + return mockResponseWithBody(HttpStatus.OK, responseAsString) + } + + static mockResponseWithBody(status, responseBody) { + return new MockResponse() + .setResponseCode(status.value()) + .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .setBody(responseBody) + } +} diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy new file mode 100644 index 0000000000..99f245ae8c --- /dev/null +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.integration.functional.ncmp + +import org.onap.cps.integration.base.CpsIntegrationSpecBase +import org.springframework.http.HttpHeaders +import org.springframework.http.MediaType + +import static org.springframework.http.HttpMethod.POST +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request + +class PolicyExecutorIntegrationSpec extends CpsIntegrationSpecBase { + + def setup() { + // Enable mocked policy executor logic + policyDispatcher.allowAll = false; + //minimum setup for 2 cm handles with alternate ids + dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': [], 'ch-2': []] + registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'fdn1') + registerCmHandle(DMI1_URL, 'ch-2', NO_MODULE_SET_TAG, 'fdn2') + } + + def cleanup() { + deregisterCmHandle(DMI1_URL, 'ch-1') + deregisterCmHandle(DMI1_URL, 'ch-2') + } + + def 'Policy Executor create request with #scenario.'() { + when: 'a pass-through write request is sent to NCMP' + def response = mvc.perform(request(POST, "/ncmp/v1/ch/$cmHandle/data/ds/ncmp-datastore:passthrough-running") + .queryParam('resourceIdentifier', 'my-resource-id') + .contentType(MediaType.APPLICATION_JSON) + .content('{ "some-json": "data" }') + .header(HttpHeaders.AUTHORIZATION, authorization)) + .andReturn().response + then: 'the expected status code is returned' + response.getStatus() == execpectedStatusCode + where: 'following parameters are used' + scenario | cmHandle | authorization || execpectedStatusCode + 'accepted cm handle' | 'ch-1' | 'mock expects "ABC"' || 201 + 'un-accepted cm handle' | 'ch-2' | 'mock expects "ABC"' || 409 + 'invalid authorization' | 'ch-1' | 'something else' || 500 + } + +} diff --git a/integration-test/src/test/resources/application.yml b/integration-test/src/test/resources/application.yml index fefae345e6..760dad01af 100644 --- a/integration-test/src/test/resources/application.yml +++ b/integration-test/src/test/resources/application.yml @@ -213,6 +213,20 @@ ncmp: init: mode: ALWAYS + policy-executor: + enabled: true + server: + address: http://localhost + port: 8790 + httpclient: + all-services: + maximumInMemorySizeInMegabytes: 1 + maximumConnectionsTotal: 10 + pendingAcquireMaxCount: 10 + connectionTimeoutInSeconds: 30 + readTimeoutInSeconds: 30 + writeTimeoutInSeconds: 30 + hazelcast: cluster-name: cps-and-ncmp-test-caches mode: |