From: seanbeirne Date: Wed, 14 Jan 2026 16:00:46 +0000 (+0000) Subject: Forward authorization header from ProvMnS to Policy Executor X-Git-Tag: 3.7.4~4 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=f5589ce66ad4bd6aa96e50ecb4c6dd1d95b7963c;p=cps.git Forward authorization header from ProvMnS to Policy Executor - Forwards with no validation to Policy Executor - Logs authorization in policy executor stub Issue-ID: CPS-3129 Change-Id: I74014bba3848534df42262a9a8397cd99d5ac2cb Signed-off-by: seanbeirne --- diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/ProvMnSController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/ProvMnSController.java index 7de3891704..4cdbc9fd16 100644 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/ProvMnSController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/ProvMnSController.java @@ -118,7 +118,8 @@ public class ProvMnSController implements ProvMnS { final RequestParameters requestParameters = ParameterHelper.extractRequestParameters(httpServletRequest); try { final YangModelCmHandle yangModelCmHandle = getAndValidateYangModelCmHandle(requestParameters); - checkPermissionForEachPatchItem(requestParameters.fdn(), patchItems, yangModelCmHandle); + checkPermissionForEachPatchItem(requestParameters.fdn(), patchItems, + yangModelCmHandle, requestParameters.authorization()); final UrlTemplateParameters urlTemplateParameters = parametersBuilder.createUrlTemplateParametersForWrite(yangModelCmHandle, requestParameters.fdn()); return dmiRestClient.synchronousPatchOperation(DATA, patchItems, urlTemplateParameters, @@ -135,7 +136,7 @@ public class ProvMnSController implements ProvMnS { final YangModelCmHandle yangModelCmHandle = getAndValidateYangModelCmHandle(requestParameters); final OperationDetails operationDetails = operationDetailsFactory.buildOperationDetails(CREATE, requestParameters, resource); - checkPermission(yangModelCmHandle, operationDetails); + checkPermission(yangModelCmHandle, operationDetails, requestParameters); final UrlTemplateParameters urlTemplateParameters = parametersBuilder.createUrlTemplateParametersForWrite(yangModelCmHandle, requestParameters.fdn()); return dmiRestClient.synchronousPutOperation(DATA, resource, urlTemplateParameters); @@ -151,7 +152,7 @@ public class ProvMnSController implements ProvMnS { final YangModelCmHandle yangModelCmHandle = getAndValidateYangModelCmHandle(requestParameters); final OperationDetails operationDetails = operationDetailsFactory.buildOperationDetailsForDelete(requestParameters.fdn()); - checkPermission(yangModelCmHandle, operationDetails); + checkPermission(yangModelCmHandle, operationDetails, requestParameters); final UrlTemplateParameters urlTemplateParameters = parametersBuilder.createUrlTemplateParametersForWrite(yangModelCmHandle, requestParameters.fdn()); return dmiRestClient.synchronousDeleteOperation(DATA, urlTemplateParameters); @@ -182,27 +183,30 @@ public class ProvMnSController implements ProvMnS { } private void checkPermission(final YangModelCmHandle yangModelCmHandle, - final OperationDetails operationDetails) { + final OperationDetails operationDetails, + final RequestParameters requestParameters) { final Map> changeRequestAsMap = new HashMap<>(1); changeRequestAsMap.put(operationDetails.className(), operationDetails.ClassInstances()); final String changeRequestAsJson = jsonObjectMapper.asJsonString(changeRequestAsMap); final int index = yangModelCmHandle.getAlternateId().length(); final String resourceIdentifier = operationDetails.parentFdn().substring(index); policyExecutor.checkPermission(yangModelCmHandle, operationDetails.operationType(), - NO_AUTHORIZATION, resourceIdentifier, changeRequestAsJson); + requestParameters.authorization(), resourceIdentifier, changeRequestAsJson); } private void checkPermissionForEachPatchItem(final String baseFdn, final List patchItems, - final YangModelCmHandle yangModelCmHandle) { + final YangModelCmHandle yangModelCmHandle, + final String authorization) { int patchItemCounter = 0; for (final PatchItem patchItem : patchItems) { final String extendedPath = baseFdn + patchItem.getPath(); - final RequestParameters requestParameters = ParameterHelper.createRequestParametersForPatch(extendedPath); + final RequestParameters requestParameters = + ParameterHelper.createRequestParametersForPatch(extendedPath, authorization); final OperationDetails operationDetails = operationDetailsFactory.buildOperationDetails(requestParameters, patchItem); try { - checkPermission(yangModelCmHandle, operationDetails); + checkPermission(yangModelCmHandle, operationDetails, requestParameters); patchItemCounter++; } catch (final Exception exception) { final String httpMethodName = "PATCH"; diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/ProvMnSControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/ProvMnSControllerSpec.groovy index b6288228d6..e956410deb 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/ProvMnSControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/ProvMnSControllerSpec.groovy @@ -234,6 +234,7 @@ class ProvMnSControllerSpec extends Specification { mockDmiRestClient.synchronousPatchOperation(*_) >> new ResponseEntity<>('content from DMI', responseStatusFromDmi) when: 'patch request is performed' def response = mvc.perform(patch(provmnsUrl) + .header('Authorization', 'my authorization') .contentType(contentMediaType) .content(jsonBody)) .andReturn().response @@ -242,7 +243,7 @@ class ProvMnSControllerSpec extends Specification { and: 'the response contains the expected content' assert response.contentAsString.contains('content from DMI') and: 'policy executor was invoked with the expected parameters' - 1 * mockPolicyExecutor.checkPermission(validCmHandle, OperationType.UPDATE, _, expectedResourceIdForPolicyExecutor, expectedChangeRequest) + 1 * mockPolicyExecutor.checkPermission(validCmHandle, OperationType.UPDATE, 'my authorization', expectedResourceIdForPolicyExecutor, expectedChangeRequest) where: 'following scenarios are applied' scenario | contentMediaType | jsonBody | responseStatusFromDmi || expectedResponseStatusFromProvMnS 'happy flow 3gpp' | patchMediaType3gpp | patchJsonBody3gpp | OK || OK @@ -299,13 +300,14 @@ class ProvMnSControllerSpec extends Specification { def expectedResourceIdentifier = '/myClass=id1/childClass=1' when: 'patch data resource request is performed' def response = mvc.perform(patch(url) + .header('Authorization', 'my authorization') .contentType(patchMediaType) .content('[{"op":"remove","path":"/childClass=1/grandchildClass=1"}]')) .andReturn().response then: 'response status is OK' assert response.status == OK.value() and: 'Policy Executor was invoked with correct details' - 1 * mockPolicyExecutor.checkPermission(_, OperationType.DELETE, _, expectedResourceIdentifier, expectedDeleteChangeRequest) + 1 * mockPolicyExecutor.checkPermission(validCmHandle, OperationType.DELETE, 'my authorization', expectedResourceIdentifier, expectedDeleteChangeRequest) } def 'Patch request with no permission from Coordination Management (aka Policy Executor).'() { @@ -386,6 +388,7 @@ class ProvMnSControllerSpec extends Specification { def expectedChangeRequest = '{"grandChildClass":[{"id":"2","attributes":{"attr1":"value1"}}]}' when: 'put data resource request is performed' def response = mvc.perform(put(putUrl) + .header('Authorization', 'my authorization') .contentType(MediaType.APPLICATION_JSON) .content(resourceAsJson)) .andReturn().response @@ -394,7 +397,7 @@ class ProvMnSControllerSpec extends Specification { and: 'the content is whatever the DMI returned' assert response.contentAsString == responseContentFromDmi and: 'The policy executor was invoked with the expected parameters' - 1 * mockPolicyExecutor.checkPermission(_, OperationType.CREATE, _, expectedResourceIdentifier, expectedChangeRequest) + 1 * mockPolicyExecutor.checkPermission(validCmHandle, OperationType.CREATE, 'my authorization', expectedResourceIdentifier, expectedChangeRequest) where: 'following responses returned by DMI' scenario | responseStatusFromDmi | responseContentFromDmi 'happy flow' | OK | 'content from DMI' @@ -427,13 +430,13 @@ class ProvMnSControllerSpec extends Specification { and: 'dmi provides a response' mockDmiRestClient.synchronousDeleteOperation(*_) >> new ResponseEntity<>(responseContentFromDmi, responseStatusFromDmi) when: 'Delete data resource request is performed' - def response = mvc.perform(delete(deleteUrl)).andReturn().response + def response = mvc.perform(delete(deleteUrl).header('Authorization', 'my authorization')).andReturn().response then: 'response status is the same as what DMI gave' assert response.status == responseStatusFromDmi.value() and: 'the content is whatever the DMI returned' assert response.contentAsString == responseContentFromDmi and: 'Policy Executor was invoked with correct resource identifier and almost empty operation details (not used for delete!)' - 1 * mockPolicyExecutor.checkPermission(_, OperationType.DELETE, _, '/myClass=id1/childClass=1', expectedDeleteChangeRequest) + 1 * mockPolicyExecutor.checkPermission(_, OperationType.DELETE, 'my authorization', '/myClass=id1/childClass=1', expectedDeleteChangeRequest) where: 'following responses returned by DMI' scenario | responseStatusFromDmi | responseContentFromDmi 'happy flow' | OK | 'content from DMI' diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/ParameterHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/ParameterHelper.java index d2903858a3..d326d68127 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/ParameterHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/ParameterHelper.java @@ -48,18 +48,21 @@ public class ParameterHelper { throw createProvMnSException(httpServletRequest.getMethod(), uriPath); } final String fdn = "/" + pathVariables[REQUEST_FDN_INDEX]; - return createRequestParameters(httpServletRequest.getMethod(), fdn); + return createRequestParameters(httpServletRequest.getMethod(), + httpServletRequest.getHeader("Authorization"), fdn); } /** * Create RequestParameters object for PATCH operations. * * @param pathWithAttributes the path a fdn possibly with containing attributes + * @param authorization HttpServletRequest object * @return RequestParameters object for PATCH operation */ - public static RequestParameters createRequestParametersForPatch(final String pathWithAttributes) { + public static RequestParameters createRequestParametersForPatch( + final String pathWithAttributes, final String authorization) { final String fdn = removeTrailingHash(extractFdn(pathWithAttributes)); - return createRequestParameters("PATCH", fdn); + return createRequestParameters("PATCH", authorization, fdn); } /** @@ -98,6 +101,7 @@ public class ParameterHelper { } private static RequestParameters createRequestParameters(final String httpMethodName, + final String authorization, final String fdn) { final int lastSlashIndex = fdn.lastIndexOf('/'); final String classNameAndId; @@ -110,7 +114,7 @@ public class ParameterHelper { } final String className = splitClassNameId[0]; final String id = removeTrailingHash(splitClassNameId[1]); - return new RequestParameters(httpMethodName, fdn, uriLdnFirstPart, className, id); + return new RequestParameters(httpMethodName, authorization, fdn, uriLdnFirstPart, className, id); } private static ProvMnSException createProvMnSException(final String httpMethodName, final String uriPath) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/RequestParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/RequestParameters.java index fb823d42a8..82adaec14b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/RequestParameters.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/provmns/RequestParameters.java @@ -22,6 +22,7 @@ package org.onap.cps.ncmp.impl.provmns; public record RequestParameters( String httpMethodName, + String authorization, String fdn, String uriLdnFirstPart, String className, diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/OperationDetailsFactorySpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/OperationDetailsFactorySpec.groovy index 19b16eec4f..31e7ea4573 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/OperationDetailsFactorySpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/OperationDetailsFactorySpec.groovy @@ -35,7 +35,7 @@ import static org.onap.cps.ncmp.api.data.models.OperationType.UPDATE class OperationDetailsFactorySpec extends Specification { def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) - def requestPathParameters = new RequestParameters('some method', '/parent=id1/someChild=someId','some uri', 'class from uri', 'id from uri') + def requestPathParameters = new RequestParameters('some method', 'some authorization', '/parent=id1/someChild=someId','some uri', 'class from uri', 'id from uri') OperationDetailsFactory objectUnderTest = new OperationDetailsFactory(jsonObjectMapper) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy index eb8cd118c2..08b37a0d01 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/provmns/ParameterHelperSpec.groovy @@ -51,7 +51,7 @@ class ParameterHelperSpec extends Specification { def 'Extract request parameters for Patch Path with attributes.'() { when: 'the request parameters are extracted from the path' - def result = objectUnderTest.createRequestParametersForPatch(path) + def result = objectUnderTest.createRequestParametersForPatch(path, 'some authorization') then: 'the FDN is as expected' assert result.fdn == expectedFdn and: 'the class name and id are mapped correctly' diff --git a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java index 91348a086d..aa4d8b0cb7 100644 --- a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java +++ b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java @@ -58,6 +58,7 @@ public class PolicyExecutorStubController implements OperationPermissionApi { final String accept, final String authorization) { log.info("Stub Policy Executor Invoked"); + log.info("Authorization sent with request: {}", authorization); log.info("Permission Request: {}", formatPermissionRequest(permissionRequest)); if (permissionRequest.getOperations().isEmpty()) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST);