From a6dac5997f249bf72cf3fef67f1049d459ea3766 Mon Sep 17 00:00:00 2001 From: guillecxb Date: Thu, 27 Mar 2025 15:56:42 +0100 Subject: [PATCH 1/8] init --- .../core/provider_enrolment_details_api.py | 2 +- .../api_provider_management/util.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 9c964345..27a1d85d 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -12,7 +12,7 @@ from .redis_internal_event import RedisInternalEvent from .resources import Resource from .responses import internal_server_error, not_found_error, forbidden_error, make_response, bad_request_error from ..core.sign_certificate import sign_certificate -from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case, negotiate_supported_features class ProviderManagementOperations(Resource): diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py index f4f15bc5..04b1ae1f 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py @@ -192,3 +192,17 @@ def _deserialize_dict(data, boxed_type): """ return {k: _deserialize(v, boxed_type) for k, v in data.items() } + +TOTAL_FEATURES = 18 +SUPPORTED_FEATURES_HEX = "201" + +def negotiate_supported_features(client_hex: str) -> str: + client_bin = bin(int(client_hex or "0", 16))[2:].zfill(TOTAL_FEATURES)[::-1] + server_bin = bin(int(SUPPORTED_FEATURES_HEX, 16))[2:].zfill(TOTAL_FEATURES)[::-1] + + negotiated_bin = ''.join([ + '1' if client_bin[i] == '1' and server_bin[i] == '1' else '0' + for i in range(TOTAL_FEATURES) + ])[::-1] + + return hex(int(negotiated_bin, 2))[2:] or "0" \ No newline at end of file -- GitLab From 3d7929b08e88412dda893f2e0abdd47946f44bc2 Mon Sep 17 00:00:00 2001 From: guillecxb Date: Fri, 28 Mar 2025 12:47:34 +0100 Subject: [PATCH 2/8] negotiate suppFeat --- .../core/provider_enrolment_details_api.py | 19 ++++++++++++++++++- .../api_provider_management/util.py | 14 -------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 27a1d85d..2866cfcf 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -12,7 +12,18 @@ from .redis_internal_event import RedisInternalEvent from .resources import Resource from .responses import internal_server_error, not_found_error, forbidden_error, make_response, bad_request_error from ..core.sign_certificate import sign_certificate -from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case, negotiate_supported_features +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case + + +TOTAL_FEATURES = 2 +SUPPORTED_FEATURES_HEX = "1" + +def negotiate_supported_features(supp_feat): + final_supp_feat = bin(int(supp_feat, 16) & int(SUPPORTED_FEATURES_HEX, 16))[2:].zfill(TOTAL_FEATURES)[::-1] + return { + "PatchUpdate": True if final_supp_feat[0] == "1" else False, + "RNAA": True if final_supp_feat[1] == "1" else False, + } class ProviderManagementOperations(Resource): @@ -49,6 +60,12 @@ class ProviderManagementOperations(Resource): api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex( 15) + + # Suppoerted Features Negotiation + client_feat = api_provider_enrolment_details.supp_feat + negotiated = negotiate_supported_features(client_feat) + api_provider_enrolment_details.supp_feat = negotiated + current_app.logger.debug(f"Negotiated supported features: {negotiated}") current_app.logger.debug("Generating certs to api prov funcs") diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py index 04b1ae1f..f4f15bc5 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py @@ -192,17 +192,3 @@ def _deserialize_dict(data, boxed_type): """ return {k: _deserialize(v, boxed_type) for k, v in data.items() } - -TOTAL_FEATURES = 18 -SUPPORTED_FEATURES_HEX = "201" - -def negotiate_supported_features(client_hex: str) -> str: - client_bin = bin(int(client_hex or "0", 16))[2:].zfill(TOTAL_FEATURES)[::-1] - server_bin = bin(int(SUPPORTED_FEATURES_HEX, 16))[2:].zfill(TOTAL_FEATURES)[::-1] - - negotiated_bin = ''.join([ - '1' if client_bin[i] == '1' and server_bin[i] == '1' else '0' - for i in range(TOTAL_FEATURES) - ])[::-1] - - return hex(int(negotiated_bin, 2))[2:] or "0" \ No newline at end of file -- GitLab From f3fc5d4ca26af47a1c5483de7c961475d279fade Mon Sep 17 00:00:00 2001 From: guillecxb Date: Fri, 28 Mar 2025 14:03:18 +0100 Subject: [PATCH 3/8] fix comment --- .../core/provider_enrolment_details_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 2866cfcf..e574fcfa 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -61,7 +61,7 @@ class ProviderManagementOperations(Resource): api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex( 15) - # Suppoerted Features Negotiation + # Supported Features Negotiation client_feat = api_provider_enrolment_details.supp_feat negotiated = negotiate_supported_features(client_feat) api_provider_enrolment_details.supp_feat = negotiated -- GitLab From 96af23566d6dd3f2917485e26201909ddd996cb4 Mon Sep 17 00:00:00 2001 From: guillecxb Date: Mon, 31 Mar 2025 17:07:26 +0200 Subject: [PATCH 4/8] suppFeat mandatory --- .../core/provider_enrolment_details_api.py | 17 +++++++++++------ .../openapi/openapi.yaml | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index e574fcfa..291e9e68 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -26,6 +26,11 @@ def negotiate_supported_features(supp_feat): } +def negotiate_supported_features_hex(supp_feat): + negotiated = int(supp_feat, 16) & int(SUPPORTED_FEATURES_HEX, 16) + return format(negotiated, 'x') + + class ProviderManagementOperations(Resource): def __check_api_provider_domain(self, api_prov_dom_id): @@ -63,9 +68,9 @@ class ProviderManagementOperations(Resource): # Supported Features Negotiation client_feat = api_provider_enrolment_details.supp_feat - negotiated = negotiate_supported_features(client_feat) - api_provider_enrolment_details.supp_feat = negotiated - current_app.logger.debug(f"Negotiated supported features: {negotiated}") + negotiated_hex = negotiate_supported_features_hex(client_feat) + api_provider_enrolment_details.supp_feat = negotiated_hex + negotiated_flags = negotiate_supported_features(negotiated_hex) current_app.logger.debug("Generating certs to api prov funcs") @@ -89,9 +94,9 @@ class ProviderManagementOperations(Resource): current_app.logger.debug("Provider inserted in database") - res = make_response(object=serialize_clean_camel_case( - api_provider_enrolment_details), status=201) - + response_obj = serialize_clean_camel_case(api_provider_enrolment_details) + response_obj["supportedFeaturesFlags"] = negotiated_flags + res = make_response(object=response_obj, status=201) res.headers['Location'] = f"https://{os.getenv("CAPIF_HOSTNAME")}/api-provider-management/v1/registrations/{str(api_provider_enrolment_details.api_prov_dom_id)}" return res diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml index 60fd3db1..d25d77f3 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml @@ -544,6 +544,7 @@ components: type: string required: - regSec + - suppFeat title: APIProviderEnrolmentDetails type: object APIProviderFunctionDetails: -- GitLab From eee424daf7f629875d6cbb18daca3c3d232d3947 Mon Sep 17 00:00:00 2001 From: guillecxb Date: Tue, 1 Apr 2025 09:24:00 +0200 Subject: [PATCH 5/8] revert swagger --- .../api_provider_management/openapi/openapi.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml index d25d77f3..60fd3db1 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml @@ -544,7 +544,6 @@ components: type: string required: - regSec - - suppFeat title: APIProviderEnrolmentDetails type: object APIProviderFunctionDetails: -- GitLab From aade85c8940b5ca7bfeec286b5b8bf21aeaa653f Mon Sep 17 00:00:00 2001 From: guillecxb Date: Tue, 1 Apr 2025 10:33:29 +0200 Subject: [PATCH 6/8] field validation --- .../core/provider_enrolment_details_api.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 291e9e68..1b88a73c 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -66,6 +66,13 @@ class ProviderManagementOperations(Resource): api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex( 15) + if api_provider_enrolment_details.supp_feat is None: + return bad_request_error( + detail="supportedFeatures not present in request", + cause="supportedFeatures not present", + invalid_params=[{"param": "supp_feat", "reason": "not defined"}] + ) + # Supported Features Negotiation client_feat = api_provider_enrolment_details.supp_feat negotiated_hex = negotiate_supported_features_hex(client_feat) -- GitLab From ba88c40ccc6ba9ca9b620b86fa134e5c3d0725f2 Mon Sep 17 00:00:00 2001 From: guillecxb Date: Wed, 2 Apr 2025 12:38:04 +0200 Subject: [PATCH 7/8] return suppFeat in the same field --- .../core/provider_enrolment_details_api.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 1b88a73c..490a9e68 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -102,7 +102,10 @@ class ProviderManagementOperations(Resource): current_app.logger.debug("Provider inserted in database") response_obj = serialize_clean_camel_case(api_provider_enrolment_details) - response_obj["supportedFeaturesFlags"] = negotiated_flags + + # ← Aquí aplicamos el cambio: sustituimos suppFeat por los flags interpretados + response_obj["suppFeat"] = negotiated_flags + res = make_response(object=response_obj, status=201) res.headers['Location'] = f"https://{os.getenv("CAPIF_HOSTNAME")}/api-provider-management/v1/registrations/{str(api_provider_enrolment_details.api_prov_dom_id)}" return res -- GitLab From 8e03d7ed1c546ab5a8995d0cf270d1703635b85e Mon Sep 17 00:00:00 2001 From: guillecxb Date: Wed, 2 Apr 2025 16:24:15 +0200 Subject: [PATCH 8/8] implementation with the negotiated hex inside of the dict --- .../core/provider_enrolment_details_api.py | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 490a9e68..a721a5aa 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -16,21 +16,16 @@ from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case TOTAL_FEATURES = 2 -SUPPORTED_FEATURES_HEX = "1" +SUPPORTED_FEATURES_HEX = "0" -def negotiate_supported_features(supp_feat): +def return_negotiated_supp_feat_dict(supp_feat): final_supp_feat = bin(int(supp_feat, 16) & int(SUPPORTED_FEATURES_HEX, 16))[2:].zfill(TOTAL_FEATURES)[::-1] return { "PatchUpdate": True if final_supp_feat[0] == "1" else False, "RNAA": True if final_supp_feat[1] == "1" else False, + "Final": hex(int(final_supp_feat[::-1], 2))[2:] } - -def negotiate_supported_features_hex(supp_feat): - negotiated = int(supp_feat, 16) & int(SUPPORTED_FEATURES_HEX, 16) - return format(negotiated, 'x') - - class ProviderManagementOperations(Resource): def __check_api_provider_domain(self, api_prov_dom_id): @@ -66,18 +61,8 @@ class ProviderManagementOperations(Resource): api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex( 15) - if api_provider_enrolment_details.supp_feat is None: - return bad_request_error( - detail="supportedFeatures not present in request", - cause="supportedFeatures not present", - invalid_params=[{"param": "supp_feat", "reason": "not defined"}] - ) - - # Supported Features Negotiation - client_feat = api_provider_enrolment_details.supp_feat - negotiated_hex = negotiate_supported_features_hex(client_feat) - api_provider_enrolment_details.supp_feat = negotiated_hex - negotiated_flags = negotiate_supported_features(negotiated_hex) + negotiated_supported_features = return_negotiated_supp_feat_dict(api_provider_enrolment_details.supp_feat) + api_provider_enrolment_details.supp_feat = negotiated_supported_features["Final"] current_app.logger.debug("Generating certs to api prov funcs") @@ -101,12 +86,9 @@ class ProviderManagementOperations(Resource): current_app.logger.debug("Provider inserted in database") - response_obj = serialize_clean_camel_case(api_provider_enrolment_details) - - # ← Aquí aplicamos el cambio: sustituimos suppFeat por los flags interpretados - response_obj["suppFeat"] = negotiated_flags + res = make_response(object=serialize_clean_camel_case( + api_provider_enrolment_details), status=201) - res = make_response(object=response_obj, status=201) res.headers['Location'] = f"https://{os.getenv("CAPIF_HOSTNAME")}/api-provider-management/v1/registrations/{str(api_provider_enrolment_details.api_prov_dom_id)}" return res @@ -167,6 +149,9 @@ class ProviderManagementOperations(Resource): if isinstance(result, Response): return result + + negotiated_supported_features = return_negotiated_supp_feat_dict(api_provider_enrolment_details.supp_feat) + api_provider_enrolment_details.supp_feat = negotiated_supported_features["Final"] for func in api_provider_enrolment_details.api_prov_funcs: if func.api_prov_func_id is None: -- GitLab