diff --git a/README.md b/README.md index f5d5bff9d87e29a9db0fbe20e2afbac4c0d69dc7..6a41e4712549ab3159f325e61f2100e8a2e02e9c 100644 --- a/README.md +++ b/README.md @@ -75,10 +75,6 @@ For that purpose Network Apps play 2 different roles when interacting with CAPIF - AEF(API Exposing Function), is responsible for the exposure of the service APIs. Assuming that API Invokers are authorized by the CCF, AEF validates the authorization and subsequently provides the direct communication entry points to the service APIs. AEF may also authorize API invokers and record the invocations in log files.One provider can have multiple AEFs -**Network Apps developers are the target users of OpenCAPIF SDK.** - -## OpenCAPIF SDK summary - OpenCAPIF SDK brings a set of functions to integrate with the 5G Core's function CAPIF, as defined in [3GPP Technical Specification (TS) 29.222 V18.5.0 Common API Framework for 3GPP Northbound APIs](https://www.etsi.org/deliver/etsi_ts/129200_129299/129222/18.05.00_60/ts_129222v180500p.pdf). This section shows the mapping between the Python functions available in this SDK and the CAPIF OpenAPI APIs defined the reference standard: | **3GPP CAPIF API** | **OpenCAPIF SDK function** | **Description** | @@ -97,7 +93,7 @@ OpenCAPIF SDK brings a set of functions to integrate with the 5G Core's function | /{apfId}/service-apis/{serviceApiId} (PUT) | [update_service()](./doc/sdk_full_documentation.md#services-update) | Updates the details of an existing service API for a specific `apfId`and `serviceApiId` | | /{apfId}/service-apis/{serviceApiId} (GET) | [get_service()](./doc/sdk_full_documentation.md#get-services) | Retrieves the details of a specific service API for a specific `apfId` and `serviceApiId` | | /{apfId}/service-apis (GET) | [get_all_services()](./doc/sdk_full_documentation.md#get-all-services) | Retrieves a list of all available service APIs for a specific `apfId` | - +| /aef-security/v1/check-authentication (POST) | [check_authentication()](./doc/sdk_full_documentation.md#check_authentication) | This custom operation allows the API invoker to confirm the `supported_features` from the API exposing function(AEF) | NOTE: Above mentioned CAPIF APIs are defined in these 3GPP references: @@ -107,6 +103,8 @@ NOTE: Above mentioned CAPIF APIs are defined in these 3GPP references: - [CAPIF Publish API specification](https://github.com/jdegre/5GC_APIs/blob/Rel-18/TS29222_CAPIF_Publish_Service_API.yaml) - [CAPIF Security API specification](https://github.com/jdegre/5GC_APIs/blob/Rel-18/TS29222_CAPIF_Security_API.yaml) +- [AEF Security API specification](https://github.com/jdegre/5GC_APIs/blob/Rel-18/TS29222_AEF_Security_API.yaml) + NOTE: In the [3GPP Technical Specification (TS) 29.222 V18.5.0 Common API Framework for 3GPP Northbound APIs](https://www.etsi.org/deliver/etsi_ts/129200_129299/129222/18.05.00_60/ts_129222v180500p.pdf) the `service` concept is understood as equal as the `API` concept. @@ -116,6 +114,14 @@ To utilize the OpenCAPIF SDK, a registered user account within the target CAPIF **Contact the administrator to obtain the required predefined credentials (CAPIF username and password).** +## OpenCAPIF SDK Data Schema + +Here is a visual look on the variables of the CAPIF sdk referenced in: +- [Important information for Invoker Consumer](#important-information-for-invoker-consumer) +- [Important information for Provider Consumer](#important-information-for-provider-consumers) + + + # Network App developer path The Network App Developer Path guides the programmer through building and integrating Network Apps using CAPIF. This path is divided into two key sections: [Invoker Network App](#invoker-network-app) and [Provider Network App](#provider-network-app). Each section covers the essential flow and functions for developing Network Apps interaction with CAPIF, whether the user is acting as an invoker consuming services or a provider offering them. By following this path, developers will gain a comprehensive understanding of how to effectively use the SDK within the CAPIF ecosystem. @@ -135,10 +141,10 @@ Now, it is described in 4 simple steps how a Provider can be developed in just s provider.onboard_provider() provider.api_description_path = "./nef_upf_vendor_1.json" - APF = provider.api_prov_funcs["APF-1"] + APF = provider.provider_capif_ids["APF-1"] - AEF1 = provider.api_prov_funcs["AEF-1"] - AEF2 = provider.api_prov_funcs["AEF-2"] + AEF1 = provider.provider_capif_ids["AEF-1"] + AEF2 = provider.provider_capif_ids["AEF-2"] provider.publish_req['publisher_apf_id'] = APF provider.publish_req['publisher_aefs_ids'] = [AEF1, AEF2] @@ -156,21 +162,16 @@ Code is next explained step by step: 2. **Onboard the Provider:** \ Register the provider with the CAPIF system to enable the publication of APIs: - In this phase, the SDK creates and stores all the necessary files for using CAPIF as a provider, such as the authorization certificate, the server certificate and each of the APFs and AEFs certificates .Furthermore creates a file named `capif_provider_details.json`, which stores important information about the provider. + In this phase, the SDK creates and stores all the necessary files for using CAPIF as a provider, such as the authorization certificate, the server certificate and each of the APFs and AEFs certificates .Furthermore creates a file named `provider_capif_ids.json`, which stores important information about the provider. 3. **Prepare API details:** \ In the `provider_folder`, more specifically in the `capif_username` folder, it will be located the provider API details file.\ This file contains all the APFs and AEFs ids that have already onboarded with this `capif_username`.\ Also it is very important to have previously prepared the API description of the API is going to be published.\ This file needs to follow the [CAPIF_Publish_Service_API](https://github.com/jdegre/5GC_APIs/blob/Rel-18/TS29222_CAPIF_Publish_Service_API.yaml). - Choose one APF and the AEFs identifiers, and fulfill the publish_req structure and the api_description_path: - - <p align="center"> - <img src="./doc/images/capif_provider_details_example.png" alt="example" width="400"/> - <img src="./doc/images/publish_req_example.png" alt="config-example" width="400"/> - </p> + Choose one APF and the AEFs identifiers, and fulfill the publish_req structure and the api_description_path. - The api_prov_funcs variable is a dictionary which contains key-values of all the APFs and AEFs stored as name: ID. + The provider_capif_ids variable is a dictionary which contains key-values of all the APFs and AEFs stored as name: ID. This publish_req field can also be filled with object variables already stored at provider object. @@ -193,18 +194,16 @@ In this sample, the provider publishes two APIs and starts running the servers o Within the `provider_folder`, the SDK stores the created folders named with prefix of the provided `capif_username` that has been registered from administrator. At each folder, there will be found the following files: -- `capif_provider_details.json`: contains all the APFs and AEFs ids that have already onboarded with this `capif_username`, +- `provider_capif_ids.json`: contains all the APFs and AEFs ids that have already onboarded with this `capif_username`, - `capif_<api_name>_<api_id>.json`: if it is already published or updated an API, it will contain a copy of the last payload, - `service_received.json`: if it is already used to get an API or get all APIs functionality, it will contain the response of last request, -- `published_apis.json`: contains the currently published APIs with their `api_id`. +- `provider_service_ids.json`: contains the currently published APIs with their `api_id`. All the configuration values are available within the object capif_provider_connector. -The api_prov_funcs variable stores the `capif_provider_details.json` content in a dictionary form. - -The published_apis variable stores the `published_apis.json` content in a dictionary form. - +The provider_service_ids variable stores the `provider_service_ids.json` content in a dictionary form. +The provider_capif_ids variable stores the `provider_capif_ids.json` content in a dictionary form. ## Invoker Network App @@ -290,7 +289,7 @@ In the `invoker_folder`, it will be located several folders with each `capif_use The `token` variable is also available for retrieving the JWT token after the get_tokens() method. -The capif_api_details variable stores the `capif_api_security_context_details.json` content in a dictionary form. +The invoker_capif_details variable stores the `capif_api_security_context_details.json` content in a dictionary form. # OpenCAPIF SDK known issues diff --git a/config/capif_sdk_config.json b/config/capif_sdk_config.json index a44b8b4c9712a17d0dcbfb29c6b558d120fe988a..36dda0240960b8ae296054341dd55827d1a81f4e 100644 --- a/config/capif_sdk_config.json +++ b/config/capif_sdk_config.json @@ -35,7 +35,6 @@ "service-kpis": "" } }, - "provider": { "provider_folder": "", "apfs": "", diff --git a/doc/images/flows_data_schema.png b/doc/images/flows_data_schema.png new file mode 100644 index 0000000000000000000000000000000000000000..d2dbeda12ae9502a563b4a5a173c1569a72bc72e Binary files /dev/null and b/doc/images/flows_data_schema.png differ diff --git a/doc/sdk_configuration.md b/doc/sdk_configuration.md index 89253ca5b3902df5bee64377a543b8e11dbf913b..e110e4b3ec0fda0dde13b56a636966d558530e8c 100644 --- a/doc/sdk_configuration.md +++ b/doc/sdk_configuration.md @@ -31,11 +31,14 @@ When configuring the SDK as a **Network App Invoker**, the following fields must - `invoker_folder` - `capif_callback_url` +- `supported_features` - `cert_generation` (fields such as `csr_common_name`, `csr_country_name`, etc.) **Optional:** To enable the discovery of specific APIs, the fields under [`discover_filter`](#configuration-of-discover_filter) can be configured. +To use `check_authentication()` it is required to fill the `ip` and `port` variables within the `check_authentication` variable + ### Network App Provider For SDK configuration as a **Network App Provider**, the following fields are required: @@ -87,6 +90,7 @@ This file can also be populated using [environment variables](../samples/envirom - [`discover_filter`](#configuration-of-discover_filter): Fields for configuring invoker service discovery. - [`publish_req`](#configuration-of-publish_req): Fields required for API publishing. - `api_description_path`: The path to the [ServiceAPIDescription](https://github.com/jdegre/5GC_APIs/blob/Rel-18/TS29222_CAPIF_Publish_Service_API.yaml) JSON file. +- `check_authentication`: The `ip` and `port` of the target Provider's AEF to get their supported features from. ## Configuration via `capif_sdk_register.json` @@ -99,10 +103,10 @@ To use this SDK in a local environment for creating and removing users, the foll - `capif_username`: The CAPIF user username. - `capif_password`: The CAPIF user password. - `config_path`: The absolute path to the configuration files folder. -- `uuid`: The UUID required for deregistering a user (only mandatory for deregistration). +- `uuid`: The UUID required for de-registering a user (only mandatory for de-registration). This file is used for the following functionalities: - Register and login. - Deregister and login. -All fields are required except for `uuid`, which is only mandatory for deregistration. It is recommended to store the `uuid` returned from the registration process for future use. +All fields are required except for `uuid`, which is only mandatory for de-registration. It is recommended to store the `uuid` returned from the registration process for future use. diff --git a/doc/sdk_full_documentation.md b/doc/sdk_full_documentation.md index 12933035438a8c1c8faf905785107cc71f756020..77f265daa60ace92ac1596ad9a22bdd88a97543c 100644 --- a/doc/sdk_full_documentation.md +++ b/doc/sdk_full_documentation.md @@ -36,17 +36,18 @@ As outlined in the [Network App developers section](../README.md), the OpenCAPIF - [Provider Network App](#provider-network-app) - [Important Information for Providers](#important-information-for-providers) - [Provider Onboarding](#provider-onboarding) - - [Service Publishing](#services-publishing) - - [Service Deletion](#services-deletion) - - [Service Updates](#services-update) + - [Service Publishing](#service-publishing) + - [Service Deletion](#service-deletion) + - [Service Updates](#service-update) - [Get Published Services](#get-services) - [Get All Published Services](#get-all-services) - [Update and Offboard Provider](#update-and-offboard-provider) - [Invoker Network App](#invoker-network-app) - [Important Information for Invokers](#important-information-for-invokers) - [Invoker Onboarding](#invoker-onboarding) - - [Service Discovery](#discover-process) - - [Obtain JWT Tokens](#obtain-invoker-tokens) + - [Service Discovery](#service-discovery) + - [Obtain JWT Tokens](#obtain-jwt-tokens) + - [Check authentication](#check-authentication) - [Update and Offboard Invoker](#update-and-offboard-invoker) - [Other Features](#other-features) - [CAPIF Registration and Login](#capif-registration-and-login) @@ -54,24 +55,22 @@ As outlined in the [Network App developers section](../README.md), the OpenCAPIF ## Provider Network App - -The OpenCAPIF SDK allows the provider flow for Network-App to be implemented with minimal code. This section provides a comprehensive overview of the SDK features relevant to CAPIF providers. +The OpenCAPIF SDK enables efficient implementation of invoker functionality for Network App. This section details the SDK features related to CAPIF providers. ### Important Information for Providers Within the `provider_folder`, directories are created based on the registered `capif_username`. Each folder contains: -- `capif_provider_details.json`: Contains all APFs and AEFs IDs onboarded with the associated username. +- `provider_service_ids.json`: Contains all APFs and AEFs IDs onboarded with the associated username. - `capif_<api_name>_<api_id>.json`: Stores the last payload for any published or updated API. - `service_received.json`: Stores responses for Get API or Get All APIs. -- `published_apis.json`: A list of currently published APIs along with their IDs. +- `provider_capif_ids.json`: A list of currently published APIs along with their IDs. All the configuration values are available within the object capif_provider_connector. -The api_prov_funcs variable stores the `capif_provider_details.json` content in a dictionary form. - -The published_apis variable stores the `published_apis.json` content in a dictionary form. +The provider_capif_ids variable stores the `provider_service_ids.json` content in a dictionary form. +The provider_capif_ids variable stores the `provider_capif_ids.json` content in a dictionary form. ### Provider Onboarding @@ -79,9 +78,7 @@ OpenCAPIF SDK references: - **Function**: `onboard_provider()` - **Script**: `provider_capif_connector.py` - -The SDK simplifies the onboarding process, allowing providers to register multiple APFs and AEFs. All APFs, AEFs, and AMF certificates are created and stored in `capif_provider_details.json`. - +The SDK simplifies the onboarding process, allowing providers to register multiple APFs and AEFs. All APFs, AEFs, and AMF certificates are created and stored in `provider_service_ids.json`.  @@ -91,12 +88,7 @@ OpenCAPIF SDK references: - **Function**: `publish_services()` - **Script**: `provider_publish_api.py` - -The SDK streamlines API publishing with the option to select specific APFs and AEFs. A copy of the uploaded API is stored in `capif_<api_name>_<api_id>.json`, and the `published_apis.json` is updated with the API name and its ID. - -**Required SDK inputs**: -- publisher_apf_id -- publisher_aefs_ids +The SDK streamlines API publishing with the option to select specific APFs and AEFs. A copy of the uploaded API is stored in `capif_<api_name>_<api_id>.json`, and the `provider_capif_ids.json` is updated with the API name and its ID. ### Service Deletion @@ -104,25 +96,17 @@ OpenCAPIF SDK references: - **Function**: `unpublish_service()` - **Script**: `provider_unpublish_api.py` - The SDK simplifies API deletion. Service deletion requires prior onboarding and service publication. -**Required SDK inputs**: -- service_api_id -- publisher_apf_id -- publisher_aefs_ids - ### Service Updates OpenCAPIF SDK references: - **Function**: `update_service()` - **Script**: `provider_update_api.py` - This function enables the updating of a previously registered API. Selecting APFs and AEFs is possible. Onboarding and service publishing are prerequisites. - **Required SDK inputs**: - service_api_id - publisher_apf_id @@ -134,21 +118,13 @@ OpenCAPIF SDK references: - **Function**: `get_service()` - **Script**: `provider_get_published_api.py` - Retrieve information on a previously published service, stored in `service_received.json`. Prior onboarding and service publication are necessary. - **Required SDK inputs**: - service_api_id - publisher_apf_id ### Get All Services - -OpenCAPIF SDK references: -- **Function**: `get_all_services()` -- **Script**: `provider_get_all_published_api.py` - - Retrieve information on all previously published services, stored in `service_received.json`. Onboarding and service publication are required. **Required SDK input**: @@ -163,9 +139,7 @@ OpenCAPIF SDK references: - **Functions**: `update_provider()` and `offboard_provider()` - **Scripts**: `provider_capif_connector_update.py` and `provider_capif_connector_offboarding.py` - -The provider must be onboarded before using these features. The `capif_sdk_config.json` must be edited for updates. - +The provider must be onboarded before using these features.  @@ -178,7 +152,6 @@ The OpenCAPIF SDK enables efficient implementation of invoker functionality for Within the `invoker_folder`, directories are created based on the registered `capif_username`. These directories contain: - - `capif_api_security_context_details.json`: Stores details about the invoker, including: 1. `api_invoker_id` 2. Discovered APIs and their information (if Service Discovery has been used) @@ -186,18 +159,16 @@ Within the `invoker_folder`, directories are created based on the registered `ca The `token` variable is also available for retrieving the JWT token after the get_tokens() functionality. -The capif_api_details variable stores the `capif_api_security_context_details.json` content. +The invoker_capif_details variable stores the `capif_api_security_context_details.json` content. -### Invoker Onboarding +### Invoker onboarding OpenCAPIF SDK references: - **Function**: `onboard_invoker()` - **Script**: `invoker_capif_connector.py` - The SDK streamlines the invoker onboarding process, storing the `api_invoker_id` in the `capif_api_security_context_details.json`. -  ### Service Discovery @@ -206,13 +177,11 @@ OpenCAPIF SDK references: - **Function**: `discover()` - **Script**: `invoker_service_discover.py` - The [discover_filter](./sdk_configuration.md) can be used to retrieve access to APIs. The invoker must be onboarded before using this function. Discovered APIs and their information are stored in `capif_api_security_context_details.json`. **Note**: A 404 warning may be received during the first discovery run, prompting registration for the security service. - - +Use the [discover_filter](./sdk_configuration.md) to retrieve access to target APIs. Ensure you are [onboarded as an invoker](#invoker-onboarding) before using this feature. ### Obtain JWT Tokens @@ -220,12 +189,25 @@ OpenCAPIF SDK references: - **Function**: `get_tokens()` - **Script**: `invoker_service_get_token.py` - The SDK facilitates JWT token creation for secure access to target APIs. This process stores JWT access token in `capif_api_security_context_details.json`. -  +### Check authentication + +OpenCAPIF SDK references: +- **Function**: `check_authentication()` + +The SDK allows the API invoker to confirm the `supported_features` from the API exposing function(AEF). + +It is important to have obtained the [JWT token](#obtain-jwt-tokens) previously. + +**Required SDK inputs**: + +- check_authentication + + + ### Update and Offboard Invoker OpenCAPIF SDK references: @@ -233,8 +215,7 @@ OpenCAPIF SDK references: - **Functions**: `update_invoker()` and `offboard_invoker()` - **Scripts**: `invoker_capif_connector_update.py` and `invoker_capif_connector_offboarding.py` -Onboarding is required before utilizing these functions. The `capif_sdk_config.json` must be edited for updates. - +Onboarding is required before utilizing these functions.  diff --git a/network_app_samples/network_app_provider_sample/network_app_provider.py b/network_app_samples/network_app_provider_sample/network_app_provider.py index c4c091367e3d51f92a4c7fd956dfa42ed5ff1a88..5bc39a15df22b4c160e37c7110360ce9cdbc60a6 100644 --- a/network_app_samples/network_app_provider_sample/network_app_provider.py +++ b/network_app_samples/network_app_provider_sample/network_app_provider.py @@ -267,27 +267,28 @@ if __name__ == "__main__": capif_connector.api_description_path = "./nef_upf_vendor_1.json" - api6g = capif_connector.api_prov_funcs["APF-1"] - api5g = capif_connector.api_prov_funcs["APF-2"] + api6g = capif_connector.provider_capif_ids["APF-1"] + api5g = capif_connector.provider_capif_ids["APF-2"] - Peñuelas = capif_connector.api_prov_funcs["AEF-1"] - Distrito = capif_connector.api_prov_funcs["AEF-2"] - Valladolid = capif_connector.api_prov_funcs["AEF-3"] + Peñuelas = capif_connector.provider_capif_ids["AEF-1"] + Distrito = capif_connector.provider_capif_ids["AEF-2"] + Valladolid = capif_connector.provider_capif_ids["AEF-3"] + + capif_connector.publish_req['publisher_apf_id'] = apis - capif_connector.publish_req['publisher_apf_id'] = api6g capif_connector.publish_req['publisher_aefs_ids'] = [Peñuelas, Distrito] capif_connector.publish_services() capif_connector.api_description_path = "./nef_upf_vendor_2.json" - capif_connector.publish_req['publisher_apf_id'] = api5g + capif_connector.publish_req['publisher_apf_id'] = apis capif_connector.publish_req['publisher_aefs_ids'] = [Peñuelas, Distrito, Valladolid] capif_connector.publish_services() - capif_connector.publish_req['service_api_id'] = capif_connector.published_apis['5G-Network-App-API'] + capif_connector.publish_req['service_api_id'] = capif_connector.provider_capif_ids['5G-Network-App-API'] capif_connector.update_service() diff --git a/sdk/capif_invoker_connector.py b/sdk/capif_invoker_connector.py index 664dbf4becc9536ae2f1882f588f306369f332c3..04cfc78d9c0619f5e42dfa65dea4ae4ca7b6a82e 100644 --- a/sdk/capif_invoker_connector.py +++ b/sdk/capif_invoker_connector.py @@ -121,7 +121,7 @@ class capif_invoker_connector: self.csr_state_or_province_name = csr_state_or_province_name self.csr_country_name = csr_country_name self.csr_email_address = csr_email_address - self.capif_api_details_filename = "capif_api_security_context_details-" + self.capif_username + ".json" + self.invoker_capif_details_filename = "capif_api_security_context_details-" + self.capif_username + ".json" self.logger.info("capif_invoker_connector initialized with the JSON parameters") @@ -162,7 +162,7 @@ class capif_invoker_connector: self.logger.info("Loading Invoker API details") path = os.path.join( self.invoker_folder, - self.capif_api_details_filename + self.invoker_capif_details_filename ) with open( path, "r" @@ -172,16 +172,16 @@ class capif_invoker_connector: def __offboard_Invoker(self) -> None: self.logger.info("Offboarding Invoker") try: - capif_api_details = self.__load_invoker_api_details() + invoker_capif_details = self.__load_invoker_api_details() url = ( self.capif_https_url + "api-invoker-management/v1/onboardedInvokers/" - + capif_api_details["api_invoker_id"] + + invoker_capif_details["api_invoker_id"] ) signed_key_crt_path = os.path.join( self.invoker_folder, - capif_api_details["user_name"] + ".crt" + invoker_capif_details["user_name"] + ".crt" ) private_key_path = os.path.join( @@ -358,7 +358,7 @@ class capif_invoker_connector: self.logger.info( "Writing API invoker ID and service discovery URL to file") path = os.path.join(self.invoker_folder, - self.capif_api_details_filename) + self.invoker_capif_details_filename) try: with open( path, "w" @@ -403,7 +403,7 @@ class capif_invoker_connector: self.logger.info( "Updating Invoker to CAPIF and creating signed certificate by giving our public key to CAPIF") try: - path = self.invoker_folder + "/" + self.capif_api_details_filename + path = self.invoker_folder + "/" + self.invoker_capif_details_filename with open(path, "r") as file: invoker_details = file.read() diff --git a/sdk/capif_provider_connector.py b/sdk/capif_provider_connector.py index 89e90fdb0112be9afdf7b7c0998789f4e3ebc755..8f0d8525ce922d0cd30e233b7a17b539cf83b227 100644 --- a/sdk/capif_provider_connector.py +++ b/sdk/capif_provider_connector.py @@ -144,15 +144,15 @@ class capif_provider_connector: # Set the CAPIF HTTPS port and construct CAPIF URLs self.capif_https_port = str(capif_https_port) - self.api_prov_funcs = {} + self.provider_capif_ids = {} - path_prov_funcs=os.path.join(self.provider_folder,"capif_provider_details.json") + path_prov_funcs=os.path.join(self.provider_folder,"provider_capif_ids.json") if os.path.exists(path_prov_funcs): - self.api_prov_funcs=self.__load_provider_api_details() + self.provider_capif_ids=self.__load_provider_api_details() - path_published=os.path.join(self.provider_folder,"published_apis.json") + path_published=os.path.join(self.provider_folder,"provider_service_ids.json") if os.path.exists(path_published): - self.published_apis=self.__load_config_file(path_published) + self.provider_service_ids=self.__load_config_file(path_published) # Construct the CAPIF HTTPS URL if len(self.capif_https_port) == 0 or int(self.capif_https_port) == 443: @@ -333,7 +333,7 @@ class capif_provider_connector: # Save the provider details provider_details_path = os.path.join( - self.provider_folder, "capif_provider_details.json") + self.provider_folder, "provider_capif_ids.json") with open(provider_details_path, "w") as outfile: data = { "capif_registration_id": capif_registration_id, @@ -342,7 +342,8 @@ class capif_provider_connector: for i, api_prov_func in enumerate(onboarding_response["apiProvFuncs"])} } for i, api_prov_func in enumerate(onboarding_response["apiProvFuncs"]): - self.api_prov_funcs[indexedroles[i]] = api_prov_func["apiProvFuncId"] + self.provider_capif_ids[indexedroles[i]] = api_prov_func["apiProvFuncId"] + json.dump(data, outfile, indent=4) self.logger.info("Data saved") @@ -417,7 +418,7 @@ class capif_provider_connector: # Load provider details provider_details_path = os.path.join( - self.provider_folder, "capif_provider_details.json") + self.provider_folder, "provider_capif_ids.json") self.logger.info( f"Loading provider details from {provider_details_path}") @@ -517,22 +518,24 @@ class capif_provider_connector: outfile.write(capif_response_text) self.logger.info(f"CAPIF response saved to {output_path}") output_path = os.path.join( - self.provider_folder, "published_apis.json") + + self.provider_folder, "provider_service_ids.json") # Read the existing file of published APIs - published_apis = {} + provider_service_ids = {} if os.path.exists(output_path): with open(output_path, "r") as outfile: - published_apis = json.load(outfile) + provider_service_ids = json.load(outfile) # Add the newly published API - published_apis[file_name] = id + provider_service_ids[file_name] = id + + self.provider_service_ids = provider_service_ids - self.published_apis = published_apis # Write the updated file of published APIs with open(output_path, "w") as outfile: - json.dump(published_apis, outfile, indent=4) + json.dump(provider_service_ids, outfile, indent=4) self.logger.info( f"API '{file_name}' with ID '{id}' added to Published Apis.") return json.loads(capif_response_text) @@ -556,7 +559,7 @@ class capif_provider_connector: """ self.logger.info("Starting the service unpublication process") provider_details_path = os.path.join( - self.provider_folder, "capif_provider_details.json") + self.provider_folder, "provider_capif_ids.json") self.logger.info( f"Loading provider details from {provider_details_path}") @@ -619,13 +622,14 @@ class capif_provider_connector: break output_path = os.path.join( - self.provider_folder, "published_apis.json") + + self.provider_folder, "provider_service_ids.json") # Read the existing file of published APIs - published_apis = {} + provider_service_ids = {} if os.path.exists(output_path): with open(output_path, "r") as outfile: - published_apis = json.load(outfile) + provider_service_ids = json.load(outfile) # API ID you want to delete # Replace with the specific ID @@ -633,13 +637,13 @@ class capif_provider_connector: # Search and delete the API by its ID api_name_to_delete = None - for name, id in published_apis.items(): + for name, id in provider_service_ids.items(): if id == api_id_to_delete: api_name_to_delete = name break if api_name_to_delete: - del published_apis[api_name_to_delete] + del provider_service_ids[api_name_to_delete] self.logger.info( f"API with ID '{api_id_to_delete}' removed from Published Apis.") else: @@ -648,8 +652,9 @@ class capif_provider_connector: # Write the updated file of published APIs with open(output_path, "w") as outfile: - json.dump(published_apis, outfile, indent=4) - self.published_apis = published_apis + + json.dump(provider_service_ids, outfile, indent=4) + self.provider_service_ids = provider_service_ids self.logger.info("Services unpublished successfully") except requests.RequestException as e: @@ -672,7 +677,7 @@ class capif_provider_connector: self.logger.info("Starting the service unpublication process") provider_details_path = os.path.join( - self.provider_folder, "capif_provider_details.json") + self.provider_folder, "provider_capif_ids.json") self.logger.info( f"Loading provider details from {provider_details_path}") @@ -746,7 +751,7 @@ class capif_provider_connector: # Load provider details provider_details_path = os.path.join( - self.provider_folder, "capif_provider_details.json") + self.provider_folder, "provider_capif_ids.json") self.logger.info( f"Loading provider details from {provider_details_path}") @@ -822,7 +827,7 @@ class capif_provider_connector: # Load provider details # Load provider details provider_details_path = os.path.join( - self.provider_folder, "capif_provider_details.json") + self.provider_folder, "provider_capif_ids.json") self.logger.info( f"Loading provider details from {provider_details_path}") @@ -936,24 +941,27 @@ class capif_provider_connector: outfile.write(capif_response_text) self.logger.info(f"CAPIF response saved to {output_path}") output_path = os.path.join( - self.provider_folder, "published_apis.json") + + self.provider_folder, "provider_service_ids.json") # Read the existing file of published APIs - published_apis = {} + provider_service_ids = {} if os.path.exists(output_path): with open(output_path, "r") as outfile: - published_apis = json.load(outfile) + provider_service_ids = json.load(outfile) keys_to_remove = [key for key, - value in published_apis.items() if value == id] + value in provider_service_ids.items() if value == id] for key in keys_to_remove: - del published_apis[key] + del provider_service_ids[key] # Add the new id of the published API - published_apis[file_name] = id - self.published_apis = published_apis + + provider_service_ids[file_name] = id + self.provider_service_ids = provider_service_ids + # Update the file with the published APIs with open(output_path, "w") as outfile: - json.dump(published_apis, outfile, indent=4) + json.dump(provider_service_ids, outfile, indent=4) self.logger.info( f"API '{file_name}' with ID '{id}' added to Published Apis.") return json.loads(capif_response_text) @@ -1046,7 +1054,7 @@ class capif_provider_connector: :raises json.JSONDecodeError: If there is an error decoding the JSON file. """ file_path = os.path.join(self.provider_folder, - "capif_provider_details.json") + "provider_capif_ids.json") try: with open(file_path, "r") as file: diff --git a/sdk/service_discoverer.py b/sdk/service_discoverer.py index 0dacba14d0b39b23643a1ab4a84e0f8db92bd383..b42d713362ce27b698a79b6f5bdab67d7784f123 100644 --- a/sdk/service_discoverer.py +++ b/sdk/service_discoverer.py @@ -108,14 +108,16 @@ class service_discoverer: os.makedirs(self.invoker_folder, exist_ok=True) # Load CAPIF API details - self.capif_api_details = self.__load_provider_api_details() + + self.invoker_capif_details = self.__load_provider_api_details() try: - self.token = self.capif_api_details["access_token"] + self.token = self.invoker_capif_details["access_token"] + except : pass # Define paths for certificates, private keys, and CA root - self.signed_key_crt_path = os.path.join(self.invoker_folder, self.capif_api_details["user_name"] + ".crt") + self.signed_key_crt_path = os.path.join(self.invoker_folder, self.invoker_capif_details["user_name"] + ".crt") self.private_key_path = os.path.join(self.invoker_folder, "private.key") self.ca_root_path = os.path.join(self.invoker_folder, "ca.crt") @@ -123,7 +125,7 @@ class service_discoverer: self.logger.info("ServiceDiscoverer initialized correctly") def get_api_provider_id(self): - return self.capif_api_details["api_provider_id"] + return self.invoker_capif_details["api_provider_id"] def __load_config_file(self, config_file: str): """Carga el archivo de configuración.""" @@ -181,7 +183,7 @@ class service_discoverer: with open( path, "w" ) as outfile: - json.dump(self.capif_api_details, outfile) + json.dump(self.invoker_capif_details, outfile) self.logger.info("Security context saved correctly") except Exception as e: self.logger.error( @@ -196,7 +198,7 @@ class service_discoverer: :param aef_id: El aef_id devuelto por descubrir servicios. :return: None. """ - url = f"https://{self.capif_host}:{self.capif_https_port}/capif-security/v1/trustedInvokers/{self.capif_api_details['api_invoker_id']}/update" + url = f"https://{self.capif_host}:{self.capif_https_port}/capif-security/v1/trustedInvokers/{self.invoker_capif_details['api_invoker_id']}/update" payload = { "securityInfo": [], "notificationDestination": "https://mynotificationdest.com", @@ -209,22 +211,23 @@ class service_discoverer: } number_of_apis = len( - self.capif_api_details["registered_security_contexes"]) - + self.invoker_capif_details["registered_security_contexes"]) + for i in range(0, number_of_apis): # Obtaining the values of api_id and aef_id for each API - api_id = self.capif_api_details["registered_security_contexes"][i]["api_id"] - aef_id = self.capif_api_details["registered_security_contexes"][i]["aef_id"] - - security_info = { - "prefSecurityMethods": ["Oauth"], - "authenticationInfo": "string", - "authorizationInfo": "string", - "aefId": aef_id, - "apiId": api_id - } - - payload["securityInfo"].append(security_info) + aef_profiles = self.invoker_capif_details["registered_security_contexes"][i]['aef_profiles'] + api_id = self.invoker_capif_details["registered_security_contexes"][i]['api_id'] + for n in range(0, len(aef_profiles)): + aef_id = self.invoker_capif_details["registered_security_contexes"][i]['aef_profiles'][n]['aef_id'] + + security_info = { + "prefSecurityMethods": ["Oauth"], + "authenticationInfo": "string", + "authorizationInfo": "string", + "aefId": aef_id, + "apiId": api_id + } + payload["securityInfo"].append(security_info) try: response = requests.post(url, @@ -256,7 +259,7 @@ class service_discoverer: :return: None """ - url = f"https://{self.capif_host}:{self.capif_https_port}/capif-security/v1/trustedInvokers/{self.capif_api_details['api_invoker_id']}" + url = f"https://{self.capif_host}:{self.capif_https_port}/capif-security/v1/trustedInvokers/{self.invoker_capif_details['api_invoker_id']}" payload = { "securityInfo": [], "notificationDestination": "https://mynotificationdest.com", @@ -269,20 +272,23 @@ class service_discoverer: } number_of_apis = len( - self.capif_api_details["registered_security_contexes"]) + self.invoker_capif_details["registered_security_contexes"]) for i in range(0, number_of_apis): # Obtaining the values of api_id and aef_id for each API - api_id = self.capif_api_details["registered_security_contexes"][i]["api_id"] - aef_id = self.capif_api_details["registered_security_contexes"][i]["aef_id"] - - security_info = { - "prefSecurityMethods": ["Oauth"], - "authenticationInfo": "string", - "authorizationInfo": "string", - "aefId": aef_id, - "apiId": api_id - } + aef_profiles = self.invoker_capif_details["registered_security_contexes"][i]['aef_profiles'] + api_id = self.invoker_capif_details["registered_security_contexes"][i]['api_id'] + for n in range(0, len(aef_profiles)): + aef_id = self.invoker_capif_details["registered_security_contexes"][i]['aef_profiles'][n]['aef_id'] + + security_info = { + "prefSecurityMethods": ["Oauth"], + "authenticationInfo": "string", + "authorizationInfo": "string", + "aefId": aef_id, + "apiId": api_id + } + payload["securityInfo"].append(security_info) payload["securityInfo"].append(security_info) @@ -306,23 +312,23 @@ class service_discoverer: :param aef_id: El aef_id relevante devuelto por descubrir servicios :return: El token de acceso (jwt) """ - url = f"https://{self.capif_host}:{self.capif_https_port}/capif-security/v1/securities/{self.capif_api_details['api_invoker_id']}/token" - # Build the scope by concatenating aef_id and api_name separated by a ';' + url = f"https://{self.capif_host}:{self.capif_https_port}/capif-security/v1/securities/{self.invoker_capif_details['api_invoker_id']}/token" + # Build the scope by concatenating aef_id and api_name separated by a ';' scope_parts = [] # Iterate over the registered contexts and build the scope parts - for context in self.capif_api_details["registered_security_contexes"]: - aef_id = context["aef_id"] + for context in self.invoker_capif_details["registered_security_contexes"]: api_name = context["api_name"] - scope_parts.append(f"{aef_id}:{api_name}") + for i in range(0, len(context['aef_profiles'])): + aef_id = context['aef_profiles'][i]['aef_id'] + scope_parts.append(f"{aef_id}:{api_name}") # Join all the scope parts with ';' and add the prefix '3gpp#' scope = "3gpp#" + ";".join(scope_parts) - payload = { "grant_type": "client_credentials", - "client_id": self.capif_api_details["api_invoker_id"], + "client_id": self.invoker_capif_details["api_invoker_id"], "client_secret": "string", "scope": scope } @@ -362,7 +368,7 @@ class service_discoverer: # Form the URL with the query parameters query_string = "&".join([f"{k}={v}" for k, v in query_params.items()]) - url = f"https://{self.capif_host}:{self.capif_https_port}/{self.capif_api_details['discover_services_url']}{self.capif_api_details['api_invoker_id']}" + url = f"https://{self.capif_host}:{self.capif_https_port}/{self.invoker_capif_details['discover_services_url']}{self.invoker_capif_details['api_invoker_id']}" if query_string: url += f"&{query_string}" @@ -438,7 +444,7 @@ class service_discoverer: return result_url def save_security_token(self, token): - self.capif_api_details["access_token"] = token + self.invoker_capif_details["access_token"] = token self.__cache_security_context() def get_tokens(self): @@ -458,18 +464,22 @@ class service_discoverer: "No endpoints have been registered. Make sure a Provider has Published an API to CAPIF first") def save_api_discovered(self, endpoints): - self.capif_api_details["registered_security_contexes"] = [] + self.invoker_capif_details["registered_security_contexes"] = [] + p = 0 for service in endpoints["serviceAPIDescriptions"]: - api_name = service["apiName"] api_id = service["apiId"] + api_name = service["apiName"] + aef_profiles = [] + self.invoker_capif_details["registered_security_contexes"].append({"api_name": api_name, "api_id": api_id, "aef_profiles": aef_profiles}) for n in service["aefProfiles"]: versions = n["versions"] aef_id = n["aefId"] for m in n["interfaceDescriptions"]: ip = m["ipv4Addr"] port = m["port"] - self.capif_api_details["registered_security_contexes"].append( - {"api_name": api_name, "api_id": api_id, "aef_id": aef_id, "ip": ip, "port": port, "versions": versions}) + self.invoker_capif_details["registered_security_contexes"][p]['aef_profiles'].append( + {"aef_id": aef_id, "ip": ip, "port": port, "versions": versions}) + p += 1 self.save_api_details() @@ -481,7 +491,7 @@ class service_discoverer: # Save the details as a JSON file with open(file_path, "w") as outfile: - json.dump(self.capif_api_details, outfile, indent=4) + json.dump(self.invoker_capif_details, outfile, indent=4) # Log the success of the operation self.logger.info("API provider details correctly saved") diff --git a/test/capif_sdk_config_sample_test.json b/test/capif_sdk_config_sample_test.json index 2bf2a12bbf3f91a88a0968779ea5c9212c2e220e..04e9d920fa099f32d0e2a9f31cc8604dccc3fbf7 100644 --- a/test/capif_sdk_config_sample_test.json +++ b/test/capif_sdk_config_sample_test.json @@ -1,23 +1,22 @@ { - - "capif_host": "", - "register_host": "", - "capif_https_port": "", - "capif_register_port": "", - "capif_username": "", - "capif_password": "", - "debug_mode": "", - "invoker": { - "invoker_folder": "", - "capif_callback_url": "", - "cert_generation": { - "csr_common_name": "", - "csr_organizational_unit": "", - "csr_organization": "", - "crs_locality": "", - "csr_state_or_province_name": "", - "csr_country_name": "", - "csr_email_address": "" + "capif_host": "capif-prev.mobilesandbox.cloud", + "register_host": "registercapif-prev.mobilesandbox.cloud", + "capif_https_port": "36212", + "capif_register_port": "36211", + "capif_username": "echeva_0", + "capif_password": "echevapass", + "debug_mode": "True", + "invoker":{ + "invoker_folder": "/Users/IDB0128/Documents/OpenCapif/test_invoker_certificate_folder", + "capif_callback_url": "http://localhost:5000", + "cert_generation":{ + "csr_common_name": "Echeva", + "csr_organizational_unit": "discovery", + "csr_organization": "telefonica", + "crs_locality": "madrid", + "csr_state_or_province_name": "madrid", + "csr_country_name": "ES", + "csr_email_address": "adios@gmail.com" }, "discover_filter": { "api-name": "", @@ -35,9 +34,18 @@ "service-kpis": "" } }, - "provider": { - "provider_folder": "", - "apfs": "1", + "provider":{ + "provider_folder": "/Users/IDB0128/Documents/OpenCapif/test_provider_certificate_folder", + "cert_generation":{ + "csr_common_name": "provider", + "csr_organizational_unit": "discovery", + "csr_organization": "telefonica", + "crs_locality": "madrid", + "csr_state_or_province_name": "madrid", + "csr_country_name": "ES", + "csr_email_address": "hola@gmail.com" + }, + "apfs": "2", "aefs": "3", "publish_req": { "service_api_id": "", @@ -47,15 +55,6 @@ "" ] }, - "cert_generation": { - "csr_common_name": "", - "csr_organizational_unit": "", - "csr_organization": "", - "crs_locality": "", - "csr_state_or_province_name": "", - "csr_country_name": "", - "csr_email_address": "" - }, "api_description_path": "" } } diff --git a/test/network_app_provider_api_spec.json b/test/network_app_provider_api_spec.json index b17a3366fe40067b5794c4f5e36d69688c323c56..e76ddb4a6f68eef965241312c977127301a7e1e7 100755 --- a/test/network_app_provider_api_spec.json +++ b/test/network_app_provider_api_spec.json @@ -1,8 +1,8 @@ { - "apiName": "Test", + "apiName": "Testtrece", "aefProfiles": [ { - "aefId": "AEF1b4324ee22d449147a840e436c4748", + "aefId": "AEF04181f9adec08df32e63448695c563", "versions": [ { "apiVersion": "v1", @@ -10,7 +10,7 @@ "resources": [ { "resourceName": "MONITORING_SUBSCRIPTIONS", - "commType": " SUBSCRIBE_NOTIFY", + "commType": "SUBSCRIBE_NOTIFY", "uri": "/{scsAsId}/subscriptions", "custOpName": "http_post", "operations": [ @@ -21,7 +21,7 @@ }, { "resourceName": "MONITORING_SUBSCRIPTION_SINGLE", - "commType": " SUBSCRIBE_NOTIFY", + "commType": "SUBSCRIBE_NOTIFY", "uri": "/{scsAsId}/subscriptions/{subscriptionId}", "custOpName": "http_get", "operations": [ @@ -39,7 +39,7 @@ "operations": [ "POST" ], - "description": "string" + "description": "Custom operation for specific request" } ] } @@ -61,7 +61,7 @@ ] }, { - "aefId": "AEFb30ab3c6eafea9974488d878be5cdc", + "aefId": "AEFfaeb54a0b8477cb93c8fa5dd89c680", "versions": [ { "apiVersion": "v1", @@ -69,7 +69,7 @@ "resources": [ { "resourceName": "TSN_LIST_PROFILES", - "commType": " SUBSCRIBE_NOTIFY", + "commType": "SUBSCRIBE_NOTIFY", "uri": "/profile", "custOpName": "http_get", "operations": [ @@ -79,7 +79,7 @@ }, { "resourceName": "TSN_DETAIL_PROFILE", - "commType": " SUBSCRIBE_NOTIFY", + "commType": "SUBSCRIBE_NOTIFY", "uri": "/profile?name={profileName}", "custOpName": "http_get", "operations": [ @@ -89,7 +89,7 @@ }, { "resourceName": "TSN_APPLY_CONFIGURATION", - "commType": " SUBSCRIBE_NOTIFY", + "commType": "SUBSCRIBE_NOTIFY", "uri": "/apply", "custOpName": "http_post", "operations": [ @@ -99,7 +99,7 @@ }, { "resourceName": "TSN_CLEAR_CONFIGURATION", - "commType": " SUBSCRIBE_NOTIFY", + "commType": "SUBSCRIBE_NOTIFY", "uri": "/clear", "custOpName": "http_post", "operations": [ @@ -115,7 +115,7 @@ "operations": [ "POST" ], - "description": "string" + "description": "Custom operation for specific request" } ] } diff --git a/test/network_app_provider_api_spec_2.json b/test/network_app_provider_api_spec_2.json index c205b637a859813f109c1359a831bfa803c0426d..1c792a449a08899d2b2cf0ac2d7643f9bb7e58c4 100755 --- a/test/network_app_provider_api_spec_2.json +++ b/test/network_app_provider_api_spec_2.json @@ -2,7 +2,7 @@ "apiName": "Test-two", "aefProfiles": [ { - "aefId": "AEFcd7d8f2b15438f5262b75ccc91d4d3", + "aefId": "AEFc4902981590674ef59c688e0d4950d", "versions": [ { "apiVersion": "v1", @@ -61,7 +61,7 @@ ] }, { - "aefId": "AEF3aca25d4e4bec6dbf49a44fd5186a7", + "aefId": "AEFfad352761d963ddf7b0d4fd3765143", "versions": [ { "apiVersion": "v1", @@ -136,7 +136,7 @@ ] }, { - "aefId": "AEF5c6d2c497f106b7a2112ddb6f6fa3a", + "aefId": "AEFcb9d5df2e59fe0b1ecc13560e64e8d", "versions": [ { "apiVersion": "v1", diff --git a/test/network_app_provider_api_spec_3.json b/test/network_app_provider_api_spec_3.json index 07b7927a4dd5d958bc9471821cb8f8e754f4bbf1..23d3d47135e3effe9a0354cdfbdf4b3b3053d4d7 100755 --- a/test/network_app_provider_api_spec_3.json +++ b/test/network_app_provider_api_spec_3.json @@ -2,7 +2,7 @@ "apiName": "Test-three", "aefProfiles": [ { - "aefId": "AEFc240eb73d1c72d6a311a26062c8ce7", + "aefId": "AEF8857df8671cb6bda96daf3ca375867", "versions": [ { "apiVersion": "v1", @@ -61,7 +61,7 @@ ] }, { - "aefId": "AEF08305d3333a26129610ae465a08907", + "aefId": "AEF4e1b2b5e7af565ccdcf69805499341", "versions": [ { "apiVersion": "v1", diff --git a/test/test.py b/test/test.py index c22138ee5e341b99bb6e0444f783957e1812e933..cb50e896d7218c11366ea2fb64810fd509a29656 100644 --- a/test/test.py +++ b/test/test.py @@ -22,31 +22,18 @@ def preparation_for_update(APFs, AEFs, second_network_app_api,capif_provider_con return capif_provider_connector -def ensure_update(Chosen_apf, Chosen_aefs, second_network_app_api,capif_provider_connector): +def ensure_update(chosen_apf, chosen_aefs, second_network_app_api,capif_provider_connector): if second_network_app_api: - # Get AEFs ids and APFs ids to publish an API - - - provider_folder = capif_provider_connector.provider_folder - - if not provider_folder: - raise ValueError("'provider_folder' value is not defined in the configuration file.") - - detailspath = os.path.join(provider_folder, "capif_provider_details.json") - if not os.path.exists(detailspath): - raise FileNotFoundError(f"File {detailspath} not found") - - with open(detailspath, 'r') as file: - details = json.load(file) + # Get AEFs ids and APFs ids to publish an APi - APF = details.get(Chosen_apf) - AEF1 = details.get(Chosen_aefs[0]) - AEF2 = details.get(Chosen_aefs[1]) - AEF3 = details.get(Chosen_aefs[2]) + APF = capif_provider_connector.provider_capif_ids[chosen_apf] + AEF1 = capif_provider_connector.provider_capif_ids[chosen_aefs[0]] + AEF2 = capif_provider_connector.provider_capif_ids[chosen_aefs[1]] + AEF3 = capif_provider_connector.provider_capif_ids[chosen_aefs[2]] if not APF or not AEF1 or not AEF2: - raise ValueError("Not all necessary values were found in 'capif_provider_details.json'") + raise ValueError("Not all necessary values were found in 'provider_service_ids.json'") # Update configuration file capif_provider_connector.publish_req['publisher_apf_id'] = APF @@ -55,44 +42,19 @@ def ensure_update(Chosen_apf, Chosen_aefs, second_network_app_api,capif_provider else: - provider_folder = capif_provider_connector.provider_folder + APF = capif_provider_connector.provider_capif_ids['APF-1'] + AEF1 = capif_provider_connector.provider_capif_ids['AEF-1'] + AEF2 = capif_provider_connector.provider_capif_ids['AEF-2'] - if not provider_folder: - raise ValueError("'provider_folder' value is not defined in the configuration file.") - - detailspath = os.path.join(provider_folder, "capif_provider_details.json") - if not os.path.exists(detailspath): - raise FileNotFoundError(f"File {detailspath} not found") - - with open(detailspath, 'r') as file: - details = json.load(file) - - APF = details.get('APF-1') - AEF1 = details.get('AEF-1') - AEF2 = details.get('AEF-2') - - if not APF or not AEF1 or not AEF2: - raise ValueError("Not all necessary values were found in 'capif_provider_details.json'") - - # Update configuration file capif_provider_connector.publish_req['publisher_apf_id'] = APF capif_provider_connector.publish_req['publisher_aefs_ids'] = [AEF1, AEF2] - capif_provider_connector.publish_services() - print("PROVIDER PUBLISH COMPLETED") - - PublishedApis = os.path.join(provider_folder,"published_apis.json") - if not os.path.exists(PublishedApis): - raise FileNotFoundError(f"File {PublishedApis} not found") - - with open(PublishedApis, 'r') as file: - PublishedApis = json.load(file) if second_network_app_api: - service_api_id = PublishedApis.get('Test-two') + service_api_id = capif_provider_connector.provider_service_ids['Test-two'] else: - service_api_id = PublishedApis.get('Test-three') + service_api_id = capif_provider_connector.provider_service_ids['Test-three'] capif_provider_connector.publish_req['service_api_id'] = service_api_id @@ -117,40 +79,29 @@ if __name__ == "__main__": try: # Initialization of the connector capif_provider_connector = capif_provider_connector(config_file=capif_sdk_config_path) + capif_provider_connector.onboard_provider() print("PROVIDER ONBOARDING COMPLETED") # Get AEFs ids and APFs ids to publish an API - provider_folder = capif_provider_connector.provider_folder - - detailspath = os.path.join(provider_folder, "capif_provider_details.json") - if not os.path.exists(detailspath): - raise FileNotFoundError(f"File {detailspath} not found") - with open(detailspath, 'r') as file: - details = json.load(file) - - APF = details.get('APF-1') - AEF1 = details.get('AEF-1') - AEF2 = details.get('AEF-2') - - if not APF or not AEF1 or not AEF2: - raise ValueError("Not all necessary values were found in 'capif_provider_details.json'") + APF1 = capif_provider_connector.provider_capif_ids['APF-1'] + APF2 = capif_provider_connector.provider_capif_ids['APF-2'] + AEF1 = capif_provider_connector.provider_capif_ids['AEF-1'] + AEF2 = capif_provider_connector.provider_capif_ids['AEF-2'] + AEF3 = capif_provider_connector.provider_capif_ids['AEF-3'] + capif_provider_connector.api_description_path="network_app_provider_api_spec.json" # Update configuration file - capif_provider_connector.publish_req['publisher_apf_id'] = APF + capif_provider_connector.publish_req['publisher_apf_id'] = APF1 capif_provider_connector.publish_req['publisher_aefs_ids'] = [AEF1, AEF2] capif_provider_connector.publish_services() print("PROVIDER PUBLISH COMPLETED") - PublishedApis = os.path.join(provider_folder,"published_apis.json") - - with open(PublishedApis, 'r') as file: - PublishedApis = json.load(file) - service_api_id = PublishedApis.get('Test') + service_api_id = capif_provider_connector.provider_service_ids["Testtrece"] capif_provider_connector.publish_req['service_api_id'] = service_api_id @@ -197,11 +148,11 @@ if __name__ == "__main__": capif_provider_connector.update_provider() - Chosen_apf = "APF-2" + chosen_apf = "APF-2" - Chosen_aefs = ["AEF-1", "AEF-3", "AEF-4"] + chosen_aefs = ["AEF-1", "AEF-3", "AEF-4"] - capif_provider_connector = ensure_update(Chosen_apf, Chosen_aefs, True,capif_provider_connector) + capif_provider_connector = ensure_update(chosen_apf, chosen_aefs, True,capif_provider_connector) print("PROVIDER UPDATE ONE COMPLETED") @@ -209,11 +160,11 @@ if __name__ == "__main__": capif_provider_connector.update_provider() - Chosen_apf = "APF-1" + chosen_apf = "APF-1" - Chosen_aefs = ["AEF-1", "AEF-2"] + chosen_aefs = ["AEF-1", "AEF-2"] - capif_provider_connector = ensure_update(Chosen_apf, Chosen_aefs, False,capif_provider_connector) + capif_provider_connector = ensure_update(chosen_apf, chosen_aefs, False,capif_provider_connector) print("PROVIDER UPDATE TWO COMPLETED")