"serviceId" : {\r
"type" : "string",\r
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",\r
- "example" : "rApp ID"\r
+ "example" : "rApp ID",\r
+ "default" : ""\r
},\r
"policyObject" : {\r
"$ref" : "#/components/schemas/PolicyObject"\r
"serviceId" : {\r
"type" : "string",\r
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",\r
- "example" : "rApp ID"\r
+ "example" : "rApp ID",\r
+ "default" : ""\r
},\r
"policyObject" : {\r
"$ref" : "#/components/schemas/PolicyObject"\r
"type" : "string"
},
"serviceId" : {
+ "default" : "",
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",
"example" : "rApp ID",
"type" : "string"
"type" : "string"
},
"serviceId" : {
+ "default" : "",
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",
"example" : "rApp ID",
"type" : "string"
type: string
example:
'rApp ID'
+ default: ""
policyObject:
$ref: '#/components/schemas/PolicyObject'
policyTypeId:
* ONAP : ccsdk oran
* ======================================================================
* Copyright (C) 2019-2022 Nordix Foundation. All rights reserved.
- * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
* ======================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
.map(this::toBody);
}
+ public Mono<ResponseEntity<String>> postWithToken(String uri, String body, String token) {
+ RequestHeadersSpec<?> request = getWebClient() //
+ .post() //
+ .uri(uri) //
+ .headers(headers -> headers.setBearerAuth(token)) //
+ .contentType(MediaType.APPLICATION_JSON) //
+ .bodyValue(body);
+ return retrieve(request);
+ }
+
public Mono<ResponseEntity<String>> putForEntity(String uri, String body) {
RequestHeadersSpec<?> request = getWebClient() //
.put() //
return Mono.error(new ServiceException("Schema validation failed", HttpStatus.BAD_REQUEST));
Ric ric = rics.getRic(policyObjectInfo.getNearRtRicId());
PolicyType policyType = policyTypes.getType(policyObjectInfo.getPolicyTypeId());
- Policy policy = helper.buildPolicy(policyObjectInfo, policyType, ric, helper.policyIdGeneration(policyObjectInfo));
+ Policy policy = helper.buildPolicy(policyObjectInfo, policyType, ric, helper.policyIdGeneration(policyObjectInfo), serverWebExchange);
return helper.isPolicyAlreadyCreated(policy,policies)
.doOnError(errorHandlingService::handleError)
.flatMap(policyBuilt -> authorizationService.authCheck(serverWebExchange, policy, AccessType.WRITE)
Policy existingPolicy = policies.getPolicy(policyId);
PolicyObjectInformation pos =
new PolicyObjectInformation(existingPolicy.getRic().getConfig().getRicId(), body, existingPolicy.getType().getId());
- Policy updatedPolicy = helper.buildPolicy(pos, existingPolicy.getType(), existingPolicy.getRic(), policyId);
+ Policy updatedPolicy = helper.buildPolicy(pos, existingPolicy.getType(), existingPolicy.getRic(), policyId, exchange);
Ric ric = existingPolicy.getRic();
return authorizationService.authCheck(exchange, updatedPolicy, AccessType.WRITE)
.doOnError(errorHandlingService::handleError)
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * ONAP : ccsdk oran
+ * ======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+ * ======================================================================
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+ package org.onap.ccsdk.oran.a1policymanagementservice.service.v3;
+
+ import java.lang.invoke.MethodHandles;
+ import java.util.Base64;
+
+ import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfo;
+ import org.onap.ccsdk.oran.a1policymanagementservice.models.v3.PolicyObjectInformation;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+ import org.springframework.http.HttpHeaders;
+ import org.springframework.stereotype.Service;
+ import org.springframework.web.server.ServerWebExchange;
+
+ import com.google.gson.JsonObject;
+ import com.google.gson.JsonParser;
+
+ @Service
+ public class TokenService {
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ // Prefix used to identify Bearer tokens in the Authorization header
+ private static final String BEARER_PREFIX = "Bearer ";
+
+
+ /**
+ * Retrieves the service ID for version 3 (v3) of the API, which uses PolicyObjectInformation.
+ *
+ * @param policyInfoValue The PolicyObjectInformation object containing the policy details.
+ * @param exchange The ServerWebExchange object that contains request and response information.
+ * @return The service ID, either from the policy information or derived from the client ID in the token.
+ */
+ public String getServiceId(PolicyObjectInformation policyInfoValue, ServerWebExchange exchange) {
+ String serviceId = policyInfoValue.getServiceId();
+ String clientId = extractClientIdFromToken(exchange);
+
+ // If the service ID from the policy is blank, use the client ID from the token instead
+ if (serviceId.isBlank()) {
+ if (clientId != null && !clientId.isBlank()) {
+ serviceId = clientId;
+ }
+ }
+ // Return the determined service ID
+ logger.debug("ServiceID extracted from token: " + serviceId);
+ return serviceId;
+ }
+
+ /**
+ * Retrieves the service ID for version 2 (v2) of the API, which uses PolicyInfo.
+ *
+ * @param policyInfoValue The PolicyInfo object containing the policy details.
+ * @param exchange The ServerWebExchange object that contains request and response information.
+ * @return The service ID, either from the policy information or derived from the client ID in the token.
+ */
+ public String getServiceId(PolicyInfo policyInfoValue, ServerWebExchange exchange) {
+ String serviceId = policyInfoValue.getServiceId();
+ String clientId = extractClientIdFromToken(exchange);
+
+ // If the service ID from the policy is blank, use the client ID from the token instead
+ if (serviceId.isBlank()) {
+ if (clientId != null && !clientId.isBlank()) {
+ serviceId = clientId;
+ }
+ }
+ // Return the determined service ID
+ logger.debug("ServiceID extracted from token: " + serviceId);
+ return serviceId;
+ }
+
+ /**
+ * Extracts the client ID from the Bearer token present in the Authorization header.
+ *
+ * @param exchange The ServerWebExchange object that contains request and response information.
+ * @return The client ID extracted from the token, or null if the token is invalid or missing.
+ */
+ private String extractClientIdFromToken(ServerWebExchange exchange) {
+ HttpHeaders headers = exchange.getRequest().getHeaders();
+ String authHeader = headers.getFirst(HttpHeaders.AUTHORIZATION);
+
+ // Check if the Authorization header exists and contains a Bearer token
+ if (authHeader != null && authHeader.startsWith(BEARER_PREFIX)) {
+ String token = authHeader.substring(BEARER_PREFIX.length());
+ return decodeClientId(token);
+ } else {
+ // Log a debug message if the Authorization header is missing or invalid
+ logger.debug("Authorization header is missing or does not contain a Bearer token");
+ }
+ return null;
+ }
+
+ /**
+ * Decodes the client ID from the JWT token.
+ *
+ * @param token The JWT token string.
+ * @return The client ID extracted from the token, or null if decoding fails.
+ */
+ private String decodeClientId(String token) {
+ try {
+ // Split the JWT token to get the payload part
+ String[] chunks = token.split("\\.");
+ Base64.Decoder decoder = Base64.getUrlDecoder();
+ String payload = new String(decoder.decode(chunks[1]));
+ JsonObject jsonObject = JsonParser.parseString(payload).getAsJsonObject();
+
+ // Return the client ID from the payload
+ return jsonObject.get("client_id").getAsString();
+ } catch (Exception e) {
+ // Log an error if decoding fails
+ logger.error("Error decoding client ID from token", e);
+ return null;
+ }
+ }
+ }
import org.onap.ccsdk.oran.a1policymanagementservice.models.v3.PolicyObjectInformation;
import org.onap.ccsdk.oran.a1policymanagementservice.models.v3.PolicyTypeInformation;
import org.onap.ccsdk.oran.a1policymanagementservice.repository.*;
+import org.onap.ccsdk.oran.a1policymanagementservice.service.v3.TokenService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class Helper {
+ @Autowired
+ private TokenService tokenService;
+
private final Services services;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
return Mono.just(ric);
}
- public Policy buildPolicy(PolicyObjectInformation policyObjectInformation, PolicyType policyType, Ric ric, String policyId) {
+ public Policy buildPolicy(PolicyObjectInformation policyObjectInformation, PolicyType policyType, Ric ric, String policyId, ServerWebExchange exchange) {
return Policy.builder()
.id(policyId)
.json(toJson(policyObjectInformation.getPolicyObject()))
.type(policyType)
.ric(ric)
- .ownerServiceId(policyObjectInformation.getServiceId() == null ? ""
- : policyObjectInformation.getServiceId())
+ .ownerServiceId(tokenService.getServiceId(policyObjectInformation, exchange))
.lastModified(Instant.now())
.isTransient(policyObjectInformation.getTransient())
.build();
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.util.FileSystemUtils;
import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.file.Path;
import java.util.Objects;
@MockitoSpyBean
private Helper helper;
+ private final String bearerToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
+ + "eyJpc3MiOiJleGFtcGxlX2lzc3VlciIsInN1YiI6IjEyMzQ1Njc4OTAiLCJhdWQiOiJteWNsaWVudCIs"
+ + "ImV4cCI6MzAwMDAwMDAwMCwiY2xpZW50X2lkIjoibXljbGllbnQiLCJyb2xlIjoidXNlciJ9."
+ + "O5QN_SWN4J1mWKyXk_-PCvOA6GF3ypv1rSdg2uTb_Ls";
+
+ private final String emptyBearerToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IiJ9."
+ + "eyJpYXQiOjE1MTYyMzkwMjJ9.uE72OfhNzhIFuyHhZyI0eYVPG6QJ7s7A-SVeKsLubCQ";
+
@BeforeEach
void init() {
testHelperTest.port = port;
responseBody.contains("{\"scope\":{\"ueId\":\"ue5200\",\"qosId\":\"qos5200\"},\"qosObjectives\":{\"priorityLevel\":5200.0}"));
}
+ private void postPolicyWithTokenAndVerify(String clientId, String serviceId, String result) throws IOException {
+ testHelperTest.addPolicyType("type1_1.2.3", "ric.1");
+ String policyBody = testHelperTest.postPolicyBody("ric.1", "type1_1.2.3", "1");
+
+ if (serviceId != null) {
+ policyBody = policyBody.replace("\"serviceId\":\"\"", "\"serviceId\":\"" + serviceId + "\"");
+ }
+
+ StepVerifier.create(testHelperTest.restClientV3().postWithToken("/policies", policyBody, clientId)
+ .then(testHelperTest.restClientV3().getForEntity("/policies" + ((serviceId != null || clientId != null) ? "?serviceId=" + result : ""))))
+ .expectNextMatches(response -> response.getBody().contains("\"policyId\":\"1\""))
+ .expectComplete()
+ .verify();
+ }
+
+ @Test
+ @DisplayName("client_id VALID + service_id NULL/EMPTY = client_id")
+ void testPostPolicyWithToken() throws IOException {
+ postPolicyWithTokenAndVerify(bearerToken, null, "myclient");
+ }
+
+ @Test
+ @DisplayName("client_id VALID + service_id VALID = service_id")
+ void testPostPolicyWithTokenAndServiceID() throws IOException {
+ postPolicyWithTokenAndVerify(bearerToken, "notmyclient", "notmyclient");
+ }
+
+ @Test
+ @DisplayName("client_id NULL + service_id EMPTY = empty")
+ void testClientIdNullServiceIdEmpty() throws Exception {
+ postPolicyWithTokenAndVerify(null, null, "");
+ }
+
+ @Test
+ @DisplayName("client_id NULL + service_id VALID = service_id")
+ void testClientIdNullServiceIdValid() throws Exception {
+ postPolicyWithTokenAndVerify(null, "validServiceId", "validServiceId");
+ }
+
+ @Test
+ @DisplayName("client_id EMPTY + service_id NULL/EMPTY = empty")
+ void testClientIdEmptyServiceIdEmpty() throws Exception {
+ postPolicyWithTokenAndVerify(emptyBearerToken, null, "");
+ }
+
+ @Test
+ @DisplayName("client_id EMPTY + service_id VALID = service_id")
+ void testEmptyClientIdServiceIdValid() throws Exception {
+ postPolicyWithTokenAndVerify(emptyBearerToken, "validServiceId", "validServiceId");
+ }
+
@Test
@DisplayName("test get Policy Status")
void testGetPolicyStatus() throws Exception {
ServerWebExchange serverWebExchange = Mockito.mock(DefaultServerWebExchange.class);
Policy policy = testHelperTest.buidTestPolicy(testHelperTest.policyObjectInfo(nonRtRicId, policyTypeName), "122344-5674");
when(helper.jsonSchemaValidation(any())).thenReturn(Boolean.TRUE);
- when(helper.buildPolicy(any(),any(), any(), any())).thenReturn(policy);
+ when(helper.buildPolicy(any(),any(), any(), any(), any())).thenReturn(policy);
when(helper.isPolicyAlreadyCreated(any(), any())).thenReturn(Mono.error(new ServiceException
("Same policy content already created with policy ID: 122344-5674", HttpStatus.BAD_REQUEST)));
Mono<ResponseEntity<PolicyObjectInformation>> responseMono = policyService.createPolicyService(testHelperTest.policyObjectInfo(nonRtRicId, policyTypeName), serverWebExchange);
" }\n" +
" }").getAsJsonObject().toString(), Map.class));
Policy updatedPolicy = testHelperTest.buidTestPolicy(updatedPolicyObjectInfo, "122344-5674");
- when(helper.buildPolicy(any(),any(), any(), any())).thenReturn(updatedPolicy);
+ when(helper.buildPolicy(any(),any(), any(), any(), any())).thenReturn(updatedPolicy);
when(helper.checkRicStateIdle(any())).thenReturn(Mono.just(updatedPolicy.getRic()));
when(helper.checkSupportedType(any(), any())).thenReturn(Mono.just(updatedPolicy.getRic()));
when(authorizationService.authCheck(any(), any(), any())).thenReturn(Mono.just(updatedPolicy));
"serviceId" : {\r
"type" : "string",\r
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",\r
- "example" : "rApp ID"\r
+ "example" : "rApp ID",\r
+ "default" : ""\r
},\r
"policyObject" : {\r
"$ref" : "#/components/schemas/PolicyObject"\r
"serviceId" : {\r
"type" : "string",\r
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",\r
- "example" : "rApp ID"\r
+ "example" : "rApp ID",\r
+ "default" : ""\r
},\r
"policyObject" : {\r
"$ref" : "#/components/schemas/PolicyObject"\r
"type" : "string"
},
"serviceId" : {
+ "default" : "",
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",
"example" : "rApp ID",
"type" : "string"
"type" : "string"
},
"serviceId" : {
+ "default" : "",
"description" : "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registered.",
"example" : "rApp ID",
"type" : "string"
type: string
example:
'rApp ID'
+ default: ""
policyObject:
$ref: '#/components/schemas/PolicyObject'
policyTypeId: