From a32efecf26823d8ddb534128196bb76eaeea0e0b Mon Sep 17 00:00:00 2001
From: yangalicace1 <royer.yangali@etsi.org>
Date: Mon, 21 Oct 2024 13:57:53 +0000
Subject: [PATCH] Deployed d8872a4 to develop in public with MkDocs 1.6.1 and
 mike 2.1.3

---
 .../deployment_guide/index.html               |    4 +-
 public/develop/search/search_index.json       |    2 +-
 public/develop/sitemap.xml                    |   52 -
 public/develop/sitemap.xml.gz                 |  Bin 382 -> 248 bytes
 .../postman/CAPIF.postman_collection.json     |  991 ---------
 .../postman/CAPIF.postman_environment.json    |  267 ---
 public/develop/testing/postman/hello_api.py   |   38 -
 public/develop/testing/postman/index.html     |  510 -----
 public/develop/testing/postman/package.json   |   16 -
 public/develop/testing/postman/script.js      |  199 --
 .../develop/testing/robotframework/index.html |  543 -----
 .../robotframework/robot_log_example.png      |  Bin 158079 -> 0 bytes
 .../robotframework/robot_report_example.png   |  Bin 183065 -> 0 bytes
 .../api_access_control_policy/index.html      | 1441 ------------
 .../service_api_description_post_example.json |  113 -
 .../testplan/api_auditing_service/index.html  |  700 ------
 .../testplan/api_discover_service/index.html  |  857 --------
 .../event_subscription.json                   |   31 -
 .../testplan/api_events_service/index.html    | 1375 ------------
 .../api_invoker_management/index.html         |  765 -------
 .../invoker_details_post_example.json         |   15 -
 .../invoker_details_put_example.json          |  393 ----
 .../invoker_getauth_example.json              |    4 -
 .../testplan/api_logging_service/index.html   |  683 ------
 .../api_logging_service/invocation_log.json   |   45 -
 .../api_provider_management/index.html        |  875 --------
 ...tails_enrolment_details_patch_example.json |   29 -
 .../provider_details_post_example.json        |   17 -
 .../provider_getauth_example.json             |    4 -
 .../testplan/api_publish_service/index.html   | 1233 -----------
 .../publisher_register_body.json              |    7 -
 .../service_api_description_post_example.json |  113 -
 .../access_token_req.json                     |    6 -
 .../access_token_req_example.json             |    5 -
 .../testplan/api_security_service/index.html  | 1946 -----------------
 .../security_notification.json                |    9 -
 .../service_security.json                     |   25 -
 .../testplan/common_operations/index.html     |  551 -----
 .../user_getauth_response_body_example.json   |   10 -
 .../user_registration_body.json               |    6 -
 public/develop/testing/testplan/index.html    |  431 ----
 41 files changed, 3 insertions(+), 14308 deletions(-)
 delete mode 100644 public/develop/testing/postman/CAPIF.postman_collection.json
 delete mode 100644 public/develop/testing/postman/CAPIF.postman_environment.json
 delete mode 100644 public/develop/testing/postman/hello_api.py
 delete mode 100644 public/develop/testing/postman/index.html
 delete mode 100644 public/develop/testing/postman/package.json
 delete mode 100644 public/develop/testing/postman/script.js
 delete mode 100644 public/develop/testing/robotframework/index.html
 delete mode 100644 public/develop/testing/robotframework/robot_log_example.png
 delete mode 100644 public/develop/testing/robotframework/robot_report_example.png
 delete mode 100644 public/develop/testing/testplan/api_access_control_policy/index.html
 delete mode 100644 public/develop/testing/testplan/api_access_control_policy/service_api_description_post_example.json
 delete mode 100644 public/develop/testing/testplan/api_auditing_service/index.html
 delete mode 100644 public/develop/testing/testplan/api_discover_service/index.html
 delete mode 100644 public/develop/testing/testplan/api_events_service/event_subscription.json
 delete mode 100644 public/develop/testing/testplan/api_events_service/index.html
 delete mode 100644 public/develop/testing/testplan/api_invoker_management/index.html
 delete mode 100644 public/develop/testing/testplan/api_invoker_management/invoker_details_post_example.json
 delete mode 100644 public/develop/testing/testplan/api_invoker_management/invoker_details_put_example.json
 delete mode 100644 public/develop/testing/testplan/api_invoker_management/invoker_getauth_example.json
 delete mode 100644 public/develop/testing/testplan/api_logging_service/index.html
 delete mode 100644 public/develop/testing/testplan/api_logging_service/invocation_log.json
 delete mode 100644 public/develop/testing/testplan/api_provider_management/index.html
 delete mode 100644 public/develop/testing/testplan/api_provider_management/provider_details_enrolment_details_patch_example.json
 delete mode 100644 public/develop/testing/testplan/api_provider_management/provider_details_post_example.json
 delete mode 100644 public/develop/testing/testplan/api_provider_management/provider_getauth_example.json
 delete mode 100644 public/develop/testing/testplan/api_publish_service/index.html
 delete mode 100644 public/develop/testing/testplan/api_publish_service/publisher_register_body.json
 delete mode 100644 public/develop/testing/testplan/api_publish_service/service_api_description_post_example.json
 delete mode 100644 public/develop/testing/testplan/api_security_service/access_token_req.json
 delete mode 100644 public/develop/testing/testplan/api_security_service/access_token_req_example.json
 delete mode 100644 public/develop/testing/testplan/api_security_service/index.html
 delete mode 100644 public/develop/testing/testplan/api_security_service/security_notification.json
 delete mode 100644 public/develop/testing/testplan/api_security_service/service_security.json
 delete mode 100644 public/develop/testing/testplan/common_operations/index.html
 delete mode 100644 public/develop/testing/testplan/common_operations/user_getauth_response_body_example.json
 delete mode 100644 public/develop/testing/testplan/common_operations/user_registration_body.json
 delete mode 100644 public/develop/testing/testplan/index.html

diff --git a/public/develop/deployment_guide/deployment_guide/index.html b/public/develop/deployment_guide/deployment_guide/index.html
index 01125bc..9d11530 100644
--- a/public/develop/deployment_guide/deployment_guide/index.html
+++ b/public/develop/deployment_guide/deployment_guide/index.html
@@ -864,7 +864,7 @@ Most of the specifications can be as specified in the <a href="#112-oracle-virtu
 <li>Size: 60GB (at least)</li>
 <li><strong>Type</strong>: VMDK</li>
 </ul>
-<p><img alt="Screenshot_from_2024-10-21_18-13-43" src="./images/deployment_guide/01_vagrant_box.jpg" /></p>
+<p><img alt="Screenshottt_from_2024-10-21_18-13-43" src="../../images/deployment_guide/01_vagrant_box.jpg" /></p>
 <p>Also, before initiating the VM and installing the OS, we'll need to:</p>
 <ul>
 <li>Disable Floppy in the 'Boot Order'</li>
@@ -897,7 +897,7 @@ At Network Adapt 1, the following port-forwarding rule must be set.</p>
 </tr>
 </tbody>
 </table>
-<p><img alt="Screenshot_from_2023-07-10_18-25-18" src="./images/deployment_guide/02_vagrant_box.jpg" /></p>
+<p><img alt="Screenshot_from_2023-07-10_18-25-18" src="./doc/images/deployment_guide/02_vagrant_box.jpg" /></p>
 <h3><u>Installing the OS</h3>
 <p></u></p>
 <p>For a Vagrant Box, it is generally suggested that the ISO's server version is used, as it is intended to be used via SSH, and any web GUI is expected to be forwarded to the host.</p>
diff --git a/public/develop/search/search_index.json b/public/develop/search/search_index.json
index f7f90b7..536e7d3 100644
--- a/public/develop/search/search_index.json
+++ b/public/develop/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Index","text":"<p>Welcome to the ETSI TeraFlowSDN (TFS) Controller wiki!</p> <p>This wiki provides a walkthrough on how to prepare your environment for executing and contributing to the ETSI SDG TeraFlowSDN. Besides, it describes how to run some example experiments.</p>"},{"location":"#try-teraflowsdn-release-30","title":"Try TeraFlowSDN Release 3.0","text":"<p>The new release launched on April 24th, 2024 incorporates a number of new features, improvements, and bug resolutions. Try it by following the guides below, and feel free to give us your feedback. See the Release Notes.</p>"},{"location":"#requisites","title":"Requisites","text":"<p>The guides and walkthroughs below make some reasonable assumptions to simplify the deployment of the TFS controller, the execution of experiments and tests, and the development of new contributions. In particular, we assume:</p> <ul> <li>A physical server or virtual machine for running the TFS controller with the following minimum specifications (check section Configure your Machine for additional details):</li> <li>4 cores / vCPUs</li> <li>8 GB of RAM (10 GB of RAM if you want to develop)</li> <li>60 GB of disk (100 GB of disk if you want to develop)</li> <li>1 NIC card</li> <li>VSCode with the Remote SSH extension</li> <li>Working machine software:</li> <li>Ubuntu Server 22.04.4 LTS or Ubuntu Server 20.04.6 LTS</li> <li>MicroK8s v1.24.17</li> </ul> <p>Use the Wiki menu in the right side of this page to navigate through the various contents of this wiki.</p>"},{"location":"#guides-and-walkthroughs","title":"Guides and Walkthroughs","text":"<p>The following guides and walkthroughs are provided:</p> <ul> <li>1. Deployment Guide</li> <li>2. Development Guide</li> <li>3. Run Experiments</li> <li>4. Features and Bugs</li> <li>5. Supported SBIs and Network Elements</li> <li>6. Supported NBIs</li> <li>7. Supported Service Handlers</li> <li>8. Troubleshooting</li> </ul>"},{"location":"#tutorials-and-tfs-virtual-machine","title":"Tutorials and TFS Virtual Machine","text":"<p>This section provides access to the links and all the materials prepared for the tutorials and hackfests involving ETSI TeraFlowSDN.</p> <ul> <li>TFS Hackfest #3 (Castelldefels, 16-17 October 2023)</li> <li> <p>The link includes explanatory material on P4 for TeraFlowSDN, the set of guided walkthrough, and the details on the interactive sessions the participants addressed (and recordings), as well as a TFS Virtual Machine (Release 2.1).</p> </li> <li> <p>TFS Hackfest #2 (Madrid, 20-21 June 2023)</p> </li> <li> <p>The link includes explanatory material on gNMI and ContainerLab for TeraFlowSDN, the set of challenges the participants addressed (and recordings), as well as a TFS Virtual Machine (Pre-Release 2.1).</p> </li> <li> <p>OFC SC472 (San Diego, 6 March 2023)</p> </li> <li> <p>The link includes a tutorial-style slide deck, as well as a TFS Virtual Machine (Release 2).</p> </li> <li> <p>TFS Hackfest #1 (Amsterdam, 20 October 2022)</p> </li> <li>The link includes a tutorial-style slide deck (and recordings), as well as a TFS Virtual Machine (Pre-Release 2).</li> </ul>"},{"location":"#versions","title":"Versions","text":"<p>New versions of TeraFlowSDN are periodically released. Each release is properly tagged and a branch is kept for its future bug fixing, if needed.</p> <ul> <li>The branch master, points always to the latest stable version of the TeraFlowSDN controller.</li> <li>The branches release/X.Y.Z, point to the code for the different release versions indicated in branch name.</li> <li>Code in these branches can be considered stable, and no new features are planned.</li> <li>In case of bugs, point releases increasing revision number (Z) might be created.</li> <li>The main development branch is named as develop.</li> <li>Use with care! Might not be stable.</li> <li>The latest developments and contributions are added to this branch for testing and validation before reaching a release. </li> </ul> <p>To choose the appropriate branch, follow the steps described in 1.3. Deploy TeraFlowSDN &gt; Checkout the Appropriate Git Branch</p>"},{"location":"#events","title":"Events","text":"<p>Find here after the list of past and future TFS Events:</p> <ul> <li>ETSI TeraFlowSDN Events </li> </ul>"},{"location":"#contact","title":"Contact","text":"<p>If your environment does not fit with the proposed assumptions and you experience issues  preparing it to work with the ETSI TeraFlowSDN controller, contact the ETSI TeraFlowSDN  SDG team through Slack</p>"},{"location":"FAQ/","title":"Frequently Asked Questions (FAQ)","text":""},{"location":"FAQ/#does-the-user-have-to-develop-the-3-elements-of-the-provider-aef-amf-and-apf","title":"Does the user have to develop the 3 elements of the provider (AEF, AMF and APF)?","text":"<p>No, you only have to make the request to the \"/onboarding\" endpoint. In it you must specify a CSR for the AEF, APF and AMF and you will receive the certificates for each of them in the response.</p>"},{"location":"FAQ/#there-is-one-party-that-publishes-the-api-and-another-that-exposes-it-what-is-the-difference","title":"There is one party that publishes the API and another that exposes it, what is the difference?","text":"<p>There are different services, the APF, intended for publishing the APIs, and the AEF, intended so that the invoker can call it. The APF is what connects to the Capif Core Function to publish the service and when the service is up, you need the AEF service so that invokers can connect to it.</p>"},{"location":"FAQ/#before-publishing-an-api-do-you-have-to-be-registered-in-capif","title":"Before publishing an API, do you have to be registered in CAPIF?","text":"<p>Yes, before publishing an API you must register using the POST /register endpoint.</p>"},{"location":"FAQ/#where-is-the-registration-done","title":"Where is the registration done?","text":"<p>Registration is done in a REST API outside of the CAPIF specification taht we have implemented.</p>"},{"location":"FAQ/#is-the-username-and-password-chosen-by-the-user-when-registering-or-is-it-assigned-when-requesting-registration-to-capif-public-instance","title":"Is the username and password chosen by the user when registering or is it assigned when requesting registration to CAPIF public instance?","text":"<p>When you make the request to the \"/endpoint\" of register, you will be returned a username and a password determined by CAPIF.</p>"},{"location":"FAQ/#what-is-a-csr","title":"What is a CSR?","text":"<p>A CSR is a Certificate Signing Request. It is a generated data block where the certificate is planned to be installed and contains key information such as public key, organization, and location, and is used to request a certificate from a certificate authority (CA). In CAPIF, 3 CSRs are necessary to register a provider, for AEF, APF and AMF.</p>"},{"location":"FAQ/#when-doing-the-register_provider-where-can-i-find-the-csrs-that-are-generated","title":"When doing the register_provider where can I find the CSRs that are generated?","text":"<p>When using the \"register_provider\" command, if you add the \"debug\" option, it shows you a json with the data used to register the provider. There we can find in the body a list of 3 elements corresponding to AEF, APF and AMF. IN each of them, the apiProbPubKey field corresponds to the CSR.</p>"},{"location":"FAQ/#how-to-use-the-example-client-capif_invoker_gui","title":"How to use the example client (CAPIF_INVOKER_GUI)?","text":"<p>First you have to make a \"./run.sh host:port\" indicating the address of the public CAPIF. Once the Docker containers are up, you have to do a \"./terminal_to_py_netapp.sh\" and then a \"python main.py\". At this point we will find ourselves in a console with some predefined commands to use the Client. If we press tab twice it will bring up the list of available commands.</p>"},{"location":"FAQ/#where-is-the-capif-public-instance-located","title":"Where is the CAPIF public instance located?","text":"<p>The CAPIF public instance can be found at the following URLs: - capif.mobilesandbox.cloud:37211 (HTTPS) - capif.mobilesandbox.cloud:37212 (HTTP)</p>"},{"location":"FAQ/#do-you-have-to-publish-3-apis-one-for-each-instance","title":"Do you have to publish 3 APIs? one for each instance?","text":"<p>No, you only have to publish a single API but each component is responsible for a specific service, whether publishing or exposing.</p>"},{"location":"FAQ/#once-the-api-is-published-is-it-always-active-or-do-you-have-to-republish-it-every-time-you-want-to-use-it","title":"Once the API is published, is it always active? Or do you have to republish it every time you want to use it?","text":"<p>It is better to unsubscribe the API every time you exit the application since otherwise it could be republished and it would be double.</p>"},{"location":"FAQ/#would-the-same-username-and-password-be-valid-for-different-invokers","title":"Would the same username and password be valid for different invokers?","text":"<p>Yes, a user can have multiple invokers at the same time, and as such, the username and password would be the same.</p>"},{"location":"FAQ/#what-is-the-notfication-destination-field-in-the-register_invoker-request","title":"What is the notfication destination field in the register_invoker request?","text":"<p>This is the callback URL used to notify events. CAPIF has an Event service to subscribe to that notifies actions such as a subscription to an API, a change in the state of an API...</p>"},{"location":"FAQ/#is-the-notification_destination-a-required-field-in-the-register_invoker","title":"Is the notification_destination a required field in the register_invoker","text":"<p>No, it is not mandatory, but if you do not enter it you will not receive any CAPIF events. For example, the APF may delete the API, you will not be notified that the API is no longer available.</p>"},{"location":"FAQ/#what-is-the-purpose-of-the-discover_service-function-in-the-invoker-client","title":"What is the purpose of the \"discover_service\" function in the invoker client?","text":"<p>The discover_service returns a json with all the services that exist exposed in CAPIF at that moment.</p>"},{"location":"FAQ/#what-is-the-purpose-of-the-get_security_auth-function-in-the-invoker-client","title":"What is the purpose of the \"get_security_auth\" function in the invoker client?","text":"<p>Sirve para pedir el token o para refrescarlo en caso de que haya caducado. You have to use that token to call the API from the invoker.</p>"},{"location":"FAQ/#what-is-the-purpose-of-the-register_security_context-function-in-the-invoker-client","title":"What is the purpose of the \"register_security_context\" function in the invoker client?","text":"<p>To consume the API it is necessary to have a Security Context registered with the data and the authentication method.</p>"},{"location":"FAQ/#is-a-user-the-same-as-an-exposer","title":"Is a user the same as an exposer?","text":"<p>No, a user registers in CAPIF and once done can have the role of invoker, provider or both.</p>"},{"location":"FAQ/#where-can-i-put-my-endpoint","title":"Where can I put my endpoint?","text":"<p>You have to set your endpoint when doing the \"publish_service\" functionality: <code>publish_service capif_ops/config_files/service_api_description_hello.json</code></p> <p>In the file \"service_api_description_hello.json\" you configure the service that is going to be exposed and by developing one to suit you, you expose your API.</p>"},{"location":"architecture/","title":"Architecture","text":""},{"location":"architecture/#architecture","title":"Architecture","text":"<p>The CAPIF architecture has three main components, Register Service, Vault and CCF, which are represented in the following image:</p> <p></p> <p>Each component is separated into different namespaces and all communications between them use Rest APIs.</p> <p>Apart from the communication between components, there are 2 other entities that can use them:</p> <ul> <li>Admin/superadmin: Responsible for managing users with the Register or carrying out special operations in the CCF.</li> <li>Users: They are those who want to use CAPIF, registering as a user in the Register and as Invoker or Provider in the CCF.</li> </ul>"},{"location":"architecture/#register-ns","title":"Register NS","text":"<p>This namespace belongs to the Register service, and we find 2 components:</p> <ul> <li>Register Service: It is responsible for managing all users who use CAPIF, in addition to providing the necessary information for its use.</li> <li>Register MONGO DATABASE: It is the Register database, in it we store all the information about registered users.</li> </ul>"},{"location":"architecture/#vault-ns","title":"Vault NS","text":"<p>This namespace belongs to Vault. </p> <p>This component is responsible for managing all CAPIF certificates, so other components such as the Register or the CCF communicate with it to create new certificates or request keys.</p>"},{"location":"architecture/#mon-ns","title":"Mon NS","text":"<p>This is the main namespace of CAPIF, since it contains all the CCF services in addition to other components:</p> <ul> <li>NGINX: Responsible for acting as a reverse proxy to distribute CAPIF requests to the different services, controlling whether or not they are authorized to access them.</li> <li>REDIS: Used for internal communication of services.</li> <li>CAPIF MONGO DATABASE: CAPIF database, where all information related to CAPIF services such as invokers, registered providers or published services is stored.</li> <li>HELPER: Service that simplifies integration with third parties such as external management portals.</li> </ul>"},{"location":"architecture/#new-architecture","title":"New Architecture","text":"<p>You can check the details of all these changes in the conversation on the OCF wiki.</p>"},{"location":"releasenotes/","title":"Releasenotes","text":""},{"location":"releasenotes/#release-100","title":"Release 1.0.0","text":""},{"location":"releasenotes/#new-features","title":"New Features","text":""},{"location":"releasenotes/#registration-flow-improved","title":"Registration Flow improved","text":"<ul> <li>Eliminated access from CAPIF to the Register user database when onboarding is performed.</li> <li>Isolation between CCF and Register services, interaction now is only by HTTPS requested between Register, CCF and Vault.</li> <li>Eliminated the \"role\" in user creation.<ul> <li>Now a user can be an invoker or a provider at the same time</li> </ul> </li> <li>Administrator User:<ul> <li>New entity in charge of registering and managing users of the register service.</li> </ul> </li> <li>UUID to identify users.<ul> <li>When you create a user, a uuid is associated with it</li> <li>The uuid will be contained in the token requested by the user and will be used to relate invokers and providers with users.</li> </ul> </li> <li>Endpoints changed and created:<ul> <li>Administrator endpoints:<ul> <li>/createUser: /register endpoint changed to createUser. Used to register new users.</li> <li>/deleteUser: /remove endpoint changed to this. Used to delete users and all the entities they had created.</li> <li>/login: Allows administrator to log in to obtain the necessary tokens for their requests.</li> <li>/refresh: Retrieve new access token token.</li> <li>/getUsers: Returns the list with all registered users.</li> </ul> </li> <li>Customer User:<ul> <li>/getauth now also returns the urls needed to use CAPIF, used by customer.</li> </ul> </li> </ul> </li> <li> <p>Security improvements:</p> <ul> <li>/login uses basic auth with administrator credentials.</li> <li>/getauth uses basic auth with customer user credentials.</li> <li>Other requests use the administrator access token obtained from login.</li> </ul> </li> <li> <p>Current fields on user creation by administrator:</p> </li> </ul> <pre><code>required_fields = {\n    \"username\": str,\n    \"password\": str,\n    \"enterprise\": str,\n    \"country\": str,\n    \"email\": str,\n    \"purpose\": str\n}\n\noptional_fields = {\n    \"phone_number\": str,\n    \"company_web\": str,\n    \"description\": str\n}\n</code></pre> <ul> <li>Test plan has been updated with the new register flow. Please check OCF Registration Flow</li> <li>Video with explanation and demonstration of new register flow New Registration Demo</li> </ul>"},{"location":"releasenotes/#new-opencapif-architecture","title":"New OpenCAPIF architecture","text":"<ul> <li>New arquitecture with separated namespaces for Vault, CCF and Register components. Communication between them now are only allowed by using REST APIs.</li> <li> <p>New helper service inside CCF, it will simplify integration with third parties like external management portals.</p> </li> <li> <p>Helper endpoints:</p> <ul> <li>/getInvokers : Get the list of invokers from CAPIF</li> <li>/getProviders: Get the list of providers from CAPIF</li> <li>/getServices : Get the list of services published in CAPIF</li> <li>/getSecurityContext : Get the list of security contexts from CAPIF</li> <li>/getEvents : Get the list of events subscriptions from CAPIF</li> <li>/deleteEntities: Removes all entities registered by a user from the register</li> </ul> </li> <li> <p>Security in the helper</p> <ul> <li>To make requests to the helper you will need a superadmin certificate and password.</li> </ul> </li> </ul>"},{"location":"releasenotes/#events-api-upgrade","title":"Events API Upgrade","text":"<ul> <li>The event management at CCF is improved, EventNotification include Event Details with required information.</li> <li>Events updated:<ul> <li>SERVICE_API_AVAILABLE and SERVICE_API_UNAVAILABLE with apiIds</li> <li>SERVICE_API_UPDATE with serviceAPIDescriptions</li> <li>API_INVOKER_ONBOARDED, API_INVOKER_UPDATED, API_INVOKER_OFFBOARDED with apiInvokerIds.</li> </ul> </li> <li>Events Included:<ul> <li>SERVICE_API_INVOCATION_SUCCESS and SERVICE_API_INVOCATION_FAILURE with invocationLogs</li> </ul> </li> <li>Test plan include 7 new tests in order to check new events implemented and scenarios of each notification implemented, with a complete check of Event Notification.</li> <li>Test plan documentation includes the new event tests OCF Event test plan documentation.</li> </ul>"},{"location":"releasenotes/#inital-implementation-of-cicd","title":"Inital implementation of CI/CD","text":"<ul> <li>The inital implementation of CI/CD on gitlab was performed.</li> <li>Detailed information in the CICD Wiki.</li> <li>Implement initial CI/CD:<ul> <li>Description of the CI process.<ul> <li>In CI phase, created design, jobs and security checks when a branch is pushed.</li> <li>The CI has jobs as:<ul> <li>Linting code, unit test (if needed),</li> <li>Build and push artifacts (images) in Git OCI register</li> <li>Security checks,</li> <li>SCA, CVS, SAST</li> <li>The vulnerabilities are exposed in Merge Request panel to be solved.</li> </ul> </li> </ul> </li> <li>Description of the CD process:<ul> <li>Defined the environments to OCF.<ul> <li>Production env.</li> <li>Pre-production env.</li> <li>Validation env.</li> <li>Dev-1, dev-2\u2026 envs (ephemeral)</li> </ul> </li> <li>Defined the naming convention to OCF releases<ul> <li>Tag in prod: v0.0.1-release</li> <li>Tag non-prod: v0.0.1-rc</li> <li>Other tags: v0.0.1-test, v0.0.1-smt</li> </ul> </li> <li>Defined the jobs of CD<ul> <li>CD ensures the deployment in multiple envs. Therefore, the CD pipeline has deploy-ocf, delete-ocf (if needed) jobs</li> </ul> </li> </ul> </li> <li>ETSI HIVE Labs:<ul> <li>Designed, created and the Kuberntes OCF cluster is running to support OCFs deployments.</li> <li>Iterating with ETSI HIVE\u2019s support to solve computing issues.<ul> <li>CPU compatibilities with OCF services (MongoDB): Fixed</li> </ul> </li> </ul> </li> </ul> </li> </ul>"},{"location":"releasenotes/#documentation","title":"Documentation","text":""},{"location":"releasenotes/#improvements-on-documentation","title":"Improvements on documentation","text":"<ul> <li>Documentation stored in OCF Documentation Repository</li> <li>Continuous Integration included at repository for web documentation:<ul> <li>Develop version of documentation is automatically generated on each merge to develop branch.</li> <li>Tagged version from main create documentation with related tag as version.</li> </ul> </li> </ul>"},{"location":"releasenotes/#technical-debt-solved","title":"Technical Debt Solved","text":""},{"location":"releasenotes/#improved-testing-with-robot-in-order-to-cover","title":"Improved Testing with Robot in order to cover","text":"<ul> <li>Support of new Register flows.</li> <li>Allow different URLs for register, ccf and vault services.</li> <li>New Variables included to manage new architecture under test.</li> <li>Mock server developed to add the functionality of write tests involving notification from Service Under Test.</li> <li>Docker image improved generation and libraries upgraded to Robot Framework 7.</li> </ul>"},{"location":"releasenotes/#improved-security-on-db","title":"Improved security on DB","text":"<ul> <li>Credentials requested to access mongo databases.</li> <li>Credentials requested also by mongo-express.</li> </ul>"},{"location":"releasenotes/#scripts-upgraded","title":"Scripts upgraded","text":"<ul> <li>Docker compose version 2 used on them.</li> <li>New cleaning script developed.</li> <li>Scripts upgraded:<ul> <li>check_services_are_running.sh: Checks if all essential services (Vault, CCF and Register) are running.</li> <li>clean_capif_docker_services.sh: Shutdowns and removes all services essential services.</li> <li>clean_capif_temporary_files.sh: Removes temporaly files from local repository. </li> <li>run.sh: Launch Essential services locally using docker compose, also monitoring can be launched.</li> <li>run_capif_tests.sh: Launch Robot Framwork Tests.</li> <li>show_logs.sh: Show locally logs of Services running.</li> <li>run_mock_server.sh: Launch mock server locally on all interfaces. This axiliary server is only used by tagged mockserver tests on Robot Framework.</li> <li>clean_mock_server.sh: Remove mock server local deployment.</li> <li>deploy.sh: This script simplify the way to download capif repository.</li> </ul> </li> </ul>"},{"location":"releasenotes/#codebase-improvements","title":"Codebase Improvements","text":"<ul> <li>Documentation is now on splitted repository OCF Documentation Repository</li> <li>Test plan was moved to OCF Documentation Repository</li> <li>Obsolote data is removed.</li> <li>Repository Reorganization: Enhanced structure and maintainability with a better directory layout and clearer module separation.</li> <li>Code Quality Enhancements: Refactored code and fixed known issues</li> </ul>"},{"location":"releasenotes/#migration-to-gunicorn","title":"Migration to GUNICORN","text":"<ul> <li>Include production server on each microservice: Release 0 use Flask developer server, now we use GUNICORN.</li> </ul>"},{"location":"releasenotes/#release-00","title":"Release 0.0","text":"<p>The APIs included in Release 0.0 are:</p> <ul> <li>JWT Authentication APIs</li> <li>CAPIF Invoker Management API</li> <li>CAPIF Publish API</li> <li>CAPIF Discover API</li> <li>CAPIF Security API</li> <li>CAPIF Events API</li> <li>CAPIF Provider Management API</li> </ul> <p>This Release also includes a Robot Test Suite for all those services and a Postman Test Suite for simple testing.</p>"},{"location":"deployment_guide/deployment_guide/","title":"1. Deployment Guide","text":"<p>This section walks you through the process of deploying TeraFlowSDN on top of a machine running MicroK8s Kubernetes platform. The guide includes the details on configuring and installing the machine, installing and  configuring MicroK8s, and deploying and reporting the status of the TeraFlowSDN  controller.</p>"},{"location":"deployment_guide/deployment_guide/#11-configure-your-machine","title":"1.1. Configure your Machine","text":"<p>In this section, we describe how to configure a machine (physical or virtual) to be used as the deployment, execution, and development environment for the ETSI TeraFlowSDN controller. Choose your preferred environment below and follow the instructions provided.</p> <p>NOTE: If you already have a remote physical server fitting the requirements specified in this section feel free to use it instead of deploying a local VM. Check 1.1.1. Physical Server for further details.</p> <p>Virtualization platforms tested are:</p> <ul> <li>Physical Server</li> <li>Oracle Virtual Box</li> <li>VMWare Fusion</li> <li>OpenStack</li> <li>Vagrant Box</li> </ul>"},{"location":"deployment_guide/deployment_guide/#111-physical-server","title":"1.1.1. Physical ServerServer SpecificationsClusterized DeploymentNetworkingOperating SystemUpgrade the Ubuntu distribution","text":"<p>This section describes how to configure a physical server for running ETSI TeraFlowSDN(TFS) controller.</p> <p>Minimum Server Specifications for development and basic deployment</p> <ul> <li>CPU: 4 cores</li> <li>RAM: 8 GB</li> <li>Disk: 60 GB</li> <li>1 GbE NIC</li> </ul> <p>Recommended Server Specifications for development and basic deployment</p> <ul> <li>CPU: 6 cores</li> <li>RAM: 12 GB</li> <li>Disk: 80 GB</li> <li>1 GbE NIC</li> </ul> <p>Server Specifications for best development and deployment experience</p> <ul> <li>CPU: 8 cores</li> <li>RAM: 32 GB</li> <li>Disk: 120 GB</li> <li>1 GbE NIC</li> </ul> <p>NOTE: the specifications listed above are provided as a reference. They depend also on the CPU clock frequency, the RAM memory, the disk technology and speed, etc.</p> <p>For development purposes, it is recommended to run the VSCode IDE (or the IDE of your choice) in a more powerful server, for instance, the recommended server specifications for development and basic deployment.</p> <p>Given that TeraFlowSDN follows a micro-services architecture, for the deployment, it might be better to use many clusterized servers with many slower cores than a single server with few highly performant cores.</p> <p>You might consider creating a cluster of machines each featuring, at least, the minimum server specifications. That solution brings you scalability in the future.</p> <p>No explicit indications are given in terms of networking besides that servers need access to the Internet for downloading dependencies, binaries, and packages while building and deploying the TeraFlowSDN components.</p> <p>Besides that, the network requirements are essentially the same than that required for running a classical Kubernetes environment. To facilitate the deployment, we extensively use MicroK8s, thus the network requirements are, essentially, the same demanded by MicroK8s, especially, if you consider creating a Kubernetes cluster.</p> <p>As a reference, the other deployment solutions based on VMs assume the VM is connected to a virtual network configured with the IP range <code>10.0.2.0/24</code> and have the gateway at IP <code>10.0.2.1</code>. The VMs have the IP address <code>10.0.2.10</code>.</p> <p>The minimum required ports to be accessible are: - 22/SSH     : for management purposes - 80/HTTP    : for the TeraFlowSDN WebUI and Grafana dashboard - 8081/HTTPS : for the CockroachDB WebUI</p> <p>Other ports might be required if you consider to deploy addons such as Kubernetes observability, etc. The details on these ports are left appart given they might vary depending on the Kubernetes environment you use.</p> <p>The recommended Operating System for deploying TeraFlowSDN is Ubuntu Server 22.04 LTS or Ubuntu Server 20.04 LTS. Other version might work, but we have not tested them. We strongly recommend using Long Term Support (LTS) versions as they provide better stability.</p> <p>Below we provide some installation guidelines: - Installation Language: English - Autodetect your keyboard - If asked, select \"Ubuntu Server\" (do not select \"Ubuntu Server (minimized)\"). - Configure static network specifications (adapt them based on your particular setup):</p> Interface IPv4 Method Subnet Address Gateway Name servers Search domains enp0s3 Manual 10.0.2.0/24 10.0.2.10 10.0.2.1 8.8.8.8,8.8.4.4 <ul> <li>Leave proxy and mirror addresses as they are</li> <li>Let the installer self-upgrade (if asked).</li> <li>Use an entire disk for the installation</li> <li>Disable setup of the disk as LVM group</li> <li>Double check that NO swap space is allocated in the partition table. Kubernetes does not work properly with SWAP.</li> <li>Configure your user and system names:</li> <li>User name: <code>TeraFlowSDN</code></li> <li>Server's name: <code>tfs-vm</code></li> <li>Username: <code>tfs</code></li> <li>Password: <code>tfs123</code></li> <li>Install Open SSH Server</li> <li>Import SSH keys, if any.</li> <li>Featured Server Snaps</li> <li>Do not install featured server snaps. It will be done manually later to illustrate how to uninstall and reinstall them in case of trouble with.</li> <li>Let the system install and upgrade the packages.</li> <li>This operation might take some minutes depending on how old is the Optical Drive ISO image you use and your Internet connection speed.</li> <li>Restart the VM when the installation is completed.</li> </ul> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul>"},{"location":"deployment_guide/deployment_guide/#112-oracle-virtual-box","title":"1.1.2. Oracle Virtual BoxCreate a NAT Network in VirtualBoxCreate VM in VirtualBox:Install Ubuntu 22.04 LTS Operating System","text":"<p>This section describes how to configure a VM for running ETSI TeraFlowSDN(TFS) controller using Oracle VirtualBox. It has been tested with VirtualBox up to version 6.1.40 r154048.</p> <p>In \"Oracle VM VirtualBox Manager\", Menu \"File &gt; Preferences... &gt; Network\", create a NAT  network with the following specifications:</p> Name CIDR DHCP IPv6 TFS-NAT-Net 10.0.2.0/24 Disabled Disabled <p>Within the newly created \"TFS-NAT-Net\" NAT network, configure the following IPv4  forwarding rules:</p> Name Protocol Host IP Host Port Guest IP Guest Port SSH TCP 127.0.0.1 2200 10.0.2.10 22 HTTP TCP 127.0.0.1 8080 10.0.2.10 80 <p>Note: IP address 10.0.2.10 is the one that will be assigned to the VM.</p> <ul> <li>Name: TFS-VM</li> <li>Type/Version: Linux / Ubuntu (64-bit)</li> <li>CPU (*): 4 vCPUs @ 100% execution capacity</li> <li>RAM: 8 GB</li> <li>Disk: 60 GB, Virtual Disk Image (VDI), Dynamically allocated</li> <li>Optical Drive ISO Image: \"ubuntu-22.04.X-live-server-amd64.iso\"</li> <li>Download the latest Long Term Support (LTS) version of the Ubuntu Server image from Ubuntu 22.04 LTS, e.g., \"ubuntu-22.04.X-live-server-amd64.iso\".</li> <li>Note: use Ubuntu Server image instead of Ubuntu Desktop to create a lightweight VM.</li> <li>Network Adapter 1 (*): enabled, attached to NAT Network \"TFS-NAT-Net\"</li> <li>Minor adjustments (*):</li> <li>Audio: disabled</li> <li>Boot order: disable \"Floppy\"</li> </ul> <p>Note: (*) settings to be editing after the VM is created.</p> <p>In \"Oracle VM VirtualBox Manager\", start the VM in normal mode, and follow the  installation procedure. Below we provide some installation guidelines: - Installation Language: English - Autodetect your keyboard - If asked, select \"Ubuntu Server\" (do not select \"Ubuntu Server (minimized)\"). - Configure static network specifications:</p> Interface IPv4 Method Subnet Address Gateway Name servers Search domains enp0s3 Manual 10.0.2.0/24 10.0.2.10 10.0.2.1 8.8.8.8,8.8.4.4 <ul> <li>Leave proxy and mirror addresses as they are</li> <li>Let the installer self-upgrade (if asked).</li> <li>Use an entire disk for the installation</li> <li>Disable setup of the disk as LVM group</li> <li>Double check that NO swap space is allocated in the partition table. Kubernetes does not work properly with SWAP.</li> <li>Configure your user and system names:</li> <li>User name: TeraFlowSDN</li> <li>Server's name: tfs-vm</li> <li>Username: tfs</li> <li>Password: tfs123</li> <li>Install Open SSH Server</li> <li>Import SSH keys, if any.</li> <li>Featured Server Snaps</li> <li>Do not install featured server snaps. It will be done manually later to illustrate how to uninstall and reinstall them in case of trouble with.</li> <li>Let the system install and upgrade the packages.</li> <li>This operation might take some minutes depending on how old is the Optical Drive ISO image you use and your Internet connection speed.</li> <li>Restart the VM when the installation is completed.</li> </ul> <p>Upgrade the Ubuntu distribution</p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul> <p>Install VirtualBox Guest Additions On VirtualBox Manager, open the VM main screen. If you are running the VM in headless  mode, right click over the VM in the VirtualBox Manager window and click \"Show\". If a dialog informing about how to leave the interface of the VM is shown, confirm  pressing \"Switch\" button. The interface of the VM should appear.</p> <p>Click menu \"Device &gt; Insert Guest Additions CD image...\"</p> <p>On the VM terminal, type:</p> <pre><code>sudo apt-get install -y linux-headers-$(uname -r) build-essential dkms\n  # This command might take some minutes depending on your VM specs and your Internet access speed.\nsudo mount /dev/cdrom /mnt/\ncd /mnt/\nsudo ./VBoxLinuxAdditions.run\n  # This command might take some minutes depending on your VM specs.\nsudo reboot\n</code></pre>"},{"location":"deployment_guide/deployment_guide/#113-vmware-fusion","title":"1.1.3. VMWare FusionCreate VM in VMWare Fusion:Install Ubuntu 22.04.1 LTS Operating SystemUpgrade the Ubuntu distribution","text":"<p>This section describes how to configure a VM for running ETSI TeraFlowSDN(TFS) controller using VMWare Fusion. It has been tested with VMWare Fusion version 12 and 13.</p> <p>In \"VMWare Fusion\" manager, create a new network from the \"Settings/Network\" menu.</p> <ul> <li>Unlock to make changes</li> <li>Press the + icon and create a new network</li> <li>Change the name to TFS-NAT-Net</li> <li>Check \"Allow virtual machines on this network to connect to external network (NAT)\"</li> <li>Do not check \"Enable IPv6\"</li> <li>Add port forwarding for HTTP and SSH</li> <li>Uncheck \"Provide address on this network via DHCP\"</li> </ul> <p>Create a new VM an Ubuntu 22.04.1 ISO:</p> <ul> <li>Display Name: TeraFlowSDN</li> <li>Username: tfs</li> <li>Password: tfs123</li> </ul> <p>On the next screen press \"Customize Settings\", save the VM and in \"Settings\" change: - Change to use 4 CPUs - Change to access 8 GB of RAM - Change disk to size 60 GB - Change the network interface to use the previously created TFS-NAT-Net</p> <p>Run the VM to start the installation.</p> <p>The installation will be automatic, without any configuration required.</p> <ul> <li>Configure the guest IP, gateway and DNS:</li> </ul> <p>Using the Network Settings for the wired connection, set the IP to 10.0.2.10,   the mask to 255.255.255.0, the gateway to 10.0.2.2 and the DNS to 10.0.2.2.</p> <ul> <li>Disable and remove swap file:</li> </ul> <p>$ sudo swapoff -a   $ sudo rm /swapfile</p> <p>Then you can remove or comment the /swapfile entry in /etc/fstab</p> <ul> <li>Install Open SSH Server</li> <li> <p>Import SSH keys, if any.</p> </li> <li> <p>Restart the VM when the installation is completed.</p> </li> </ul> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre>"},{"location":"deployment_guide/deployment_guide/#114-openstack","title":"1.1.4. OpenStackCreate a Security Group in OpenStack <p> In OpenStack, go to Project - Network - Security Groups - Create Security Group with name TFS</p> <p>Add the following rules:</p>    Direction Ether Type IP Protocol Port Range Remote IP Prefix     Ingress IPv4 TCP 22 (SSH) 0.0.0.0/0   Ingress IPv4 TCP 2200 0.0.0.0/0   Ingress IPv4 TCP 8080 0.0.0.0/0   Ingress IPv4 TCP 80 0.0.0.0/0   Egress IPv4 Any Any 0.0.0.0/0   Egress IPv6 Any Any ::/0    <p>Note: The IP address will be assigned depending on the network you have configured inside OpenStack. This IP will have to be modified in TeraFlow configuration files which by default use IP 10.0.2.10</p> Create a flavour <p></p> <p>From dashboard (Horizon)</p> <p>Go to Admin - Compute - Flavors and press Create Flavor</p> <ul> <li>Name: TFS</li> <li>VCPUs: 4</li> <li>RAM (MB): 8192</li> <li>Root Disk (GB): 60</li> </ul> <p>From CLI</p> <pre><code> openstack flavor create TFS --id auto --ram 8192 --disk 60 --vcpus 8\n</code></pre> Create an instance in OpenStack: <p></p> <ul> <li>Instance name: TFS-VM</li> <li>Origin: [Ubuntu-22.04 cloud image] (https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img)</li> <li>Create new volume: No</li> <li>Flavor: TFS</li> <li>Networks: extnet </li> <li>Security Groups: TFS</li> <li>Configuration: Include the following cloud-config</li> </ul> <pre><code>#cloud-config\n# Modifies the password for the VM instance\nusername: ubuntu\npassword: &lt;your-password&gt;\nchpasswd: { expire: False }\nssh_pwauth: True\n</code></pre> Upgrade the Ubuntu distribution <p></p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul>","text":"<p>This section describes how to configure a VM for running ETSI TeraFlowSDN(TFS) controller using OpenStack. It has been tested with OpenStack Kolla up to Yoga version. </p>"},{"location":"deployment_guide/deployment_guide/#115-vagrant-box","title":"1.1.5. Vagrant Box <p>This section describes how to create a Vagrant Box, using the base virtual machine configured in Oracle Virtual Box.</p> Virtual Machine specifications <p> Most of the specifications can be as specified in the Oracle Virtual Box page, however, there are a few particularities to Vagrant that must be accommodated, such as:</p> <ul> <li>Virtual Hard Disk</li> <li>Size: 60GB (at least)</li> <li>Type: VMDK</li> </ul> <p></p> <p>Also, before initiating the VM and installing the OS, we'll need to:</p> <ul> <li>Disable Floppy in the 'Boot Order'</li> <li>Disable audio</li> <li>Disable USB</li> <li>Ensure Network Adapter 1 is set to NAT</li> </ul> Network configurations <p> At Network Adapt 1, the following port-forwarding rule must be set.</p>    Name Protocol Host IP Host Port Guest IP Guest Port     SSH TCP  2222  22    <p></p> Installing the OS <p></p> <p>For a Vagrant Box, it is generally suggested that the ISO's server version is used, as it is intended to be used via SSH, and any web GUI is expected to be forwarded to the host.</p> <p></p> <p></p> <p></p> <p>Make sure the disk is not configured as an LVM group!</p> <p></p> Vagrant ser <p> Vagrant expects by default, that in the box's OS exists the user <code>vagrant</code> with the password also being <code>vagrant</code>.</p> <p></p> SSH <p></p> <p>Vagrant uses SSH to connect to the boxes, so installing it now will save the hassle of doing it later.</p> <p></p> Features server snaps <p></p> <p>Do not install featured server snaps. It will be done manually later to illustrate how to uninstall and reinstall them in case of trouble with.</p> Updates <p></p> <p>Let the system install and upgrade the packages. This operation might take some minutes depending on how old is the Optical Drive ISO image you use and your Internet connection speed.</p> Upgrade the Ubuntu distribution <p></p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul> Install VirtualBox Guest Additions <p> On VirtualBox Manager, open the VM main screen. If you are running the VM in headless  mode, right-click over the VM in the VirtualBox Manager window, and click \"Show\". If a dialog informing about how to leave the interface of the VM is shown, confirm  by pressing the \"Switch\" button. The interface of the VM should appear.</p> <p>Click the menu \"Device &gt; Insert Guest Additions CD image...\"</p> <p>On the VM terminal, type:</p> <pre><code>sudo apt-get install -y linux-headers-$(uname -r) build-essential dkms\n  # This command might take some minutes depending on your VM specs and your Internet access speed.\nsudo mount /dev/cdrom /mnt/\ncd /mnt/\nsudo ./VBoxLinuxAdditions.run\n  # This command might take some minutes depending on your VM specs.\nsudo reboot\n</code></pre> ETSI TFS Installation <p> After this, proceed to 1.2. Install Microk8s, after which, return to this wiki to finish the Vagrant Box creation.</p> Box configuration and creation <p> Make sure the ETSI TFS controller is correctly configured. You will not be able to change it after!</p> <p>It is advisable to do the next configurations from a host's terminal, via a SSH connection.</p> <pre><code>ssh -p 2222 vagrant@127.0.0.1\n</code></pre> Set root password <p> Set the root password to <code>vagrant</code>.</p> <pre><code>sudo passwd root\n</code></pre> Set the superuser <p> Set up the Vagrant user so that it\u2019s able to use sudo without being prompted for a password. Anything in the <code>/etc/sudoers.d/*</code> directory is included in the sudoers privileges when created by the root user. Create a new sudo file.</p> <pre><code>sudo visudo -f /etc/sudoers.d/vagrant\n</code></pre> <p>and add the following lines</p> <pre><code># add vagrant user\nvagrant ALL=(ALL) NOPASSWD:ALL\n</code></pre> <p>You can now test that it works by running a simple command.</p> <pre><code>sudo pwd\n</code></pre> <p>Issuing this command should result in an immediate response without a request for a password.</p> Install the Vagrant key <p> Vagrant uses a default set of SSH keys for you to directly connect to boxes via the CLI command <code>vagrant ssh</code>, after which it creates a new set of SSH keys for your new box. Because of this, we need to load the default key to be able to access the box after created.</p> <pre><code>chmod 0700 /home/vagrant/.ssh\nwget --no-check-certificate https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub -O /home/vagrant/.ssh/authorized_keys\nchmod 0600 /home/vagrant/.ssh/authorized_keys\nchown -R vagrant /home/vagrant/.ssh\n</code></pre> Configure the OpenSSH Server <p> Edit the <code>/etc/ssh/sshd_config</code> file:</p> <pre><code>sudo vim /etc/ssh/sshd_config\n</code></pre> <p>And uncomment the following line:</p> <pre><code>AuthorizedKeysFile %h/.ssh/authorized_keys\n</code></pre> <p>Then restart SSH.</p> <pre><code>sudo service ssh restart\n</code></pre> Package the box <p> Before you package the box, if you intend to make your box public, it is best to clean your bash history with:</p> <pre><code>history -c\n</code></pre> <p>Exit the SSH connection, and at you're host machine, package the VM:</p> <pre><code>vagrant package --base teraflowsdncontroller --output teraflowsdncontroller.box\n</code></pre> Test run the box <p> Add the base box to you local Vagrant box list:</p> <pre><code>vagrant box add --name teraflowsdncontroller ./teraflowsdncontroller.box\n</code></pre> <p>Now you should try to run it, for that you'll need to create a Vagrantfile. For a simple run, this is the minimal required code for this box:</p> <pre><code># -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n  config.vm.box = \"teraflowsdncontroller\"\n  config.vm.box_version = \"1.1.0\"\n  config.vm.network :forwarded_port, host: 8080 ,guest: 80\nend\n</code></pre> <p>Now you'll be able to spin up the virtual machine by issuing the command:</p> <pre><code>vagrant up\n</code></pre> <p>And connect to the machine using:</p> <pre><code>vagrant ssh\n</code></pre> Pre-configured boxes <p> If you do not wish to create your own Vagrant Box, you can use one of the existing ones created by TFS contributors. - davidjosearaujo/teraflowsdncontroller - ... </p> <p>To use them, you simply have to create a Vagrantfile and run <code>vagrant up controller</code> in the same directory. The following example Vagrantfile already allows you to do just that, with the bonus of exposing the multiple management GUIs to your <code>localhost</code>.</p> <pre><code>Vagrant.configure(\"2\") do |config|\n\n  config.vm.define \"controller\" do |controller|\n    controller.vm.box = \"davidjosearaujo/teraflowsdncontroller\"\n    controller.vm.network \"forwarded_port\", guest: 80, host: 8080     # WebUI\n    controller.vm.network \"forwarded_port\", guest: 8084, host: 50750  # Linkerd Viz Dashboard\n    controller.vm.network \"forwarded_port\", guest: 8081, host: 8081   # CockroachDB Dashboard\n    controller.vm.network \"forwarded_port\", guest: 8222, host: 8222   # NATS Dashboard\n    controller.vm.network \"forwarded_port\", guest: 9000, host: 9000   # QuestDB Dashboard\n    controller.vm.network \"forwarded_port\", guest: 9090, host: 9090   # Prometheus Dashboard\n\n    # Setup Linkerd Viz reverse proxy\n    ## Copy config file\n    controller.vm.provision \"file\" do |f|\n      f.source = \"./reverse-proxy-linkerdviz.sh\"\n      f.destination = \"./reverse-proxy-linkerdviz.sh\"\n    end\n    ## Execute configuration file\n    controller.vm.provision \"shell\" do |s|\n      s.inline = \"chmod +x ./reverse-proxy-linkerdviz.sh &amp;&amp; ./reverse-proxy-linkerdviz.sh\"\n    end\n\n    # Update controller source code to the desired branch\n    if ENV['BRANCH'] != nil\n      controller.vm.provision \"shell\" do |s|\n        s.inline = \"cd ./tfs-ctrl &amp;&amp; git pull &amp;&amp; git switch \" + ENV['BRANCH']\n      end\n    end\n\n  end\nend\n</code></pre> <p>This Vagrantfile also allows for optional repository updates on startup by running the command with a specified environment variable <code>BRANCH</code></p> <pre><code>BRANCH=develop vagrant up controller\n</code></pre> Linkerd DNS rebinding bypass <p> Because of Linkerd's security measures against DNS rebinding, a reverse proxy, that modifies the request's header <code>Host</code> field, is needed to expose the GUI to the host. The previous Vagrantfile already deploys such configurations, for that, all you need to do is create the <code>reverse-proxy-linkerdviz.sh</code> file in the same directory. The content of this file is displayed below.</p> <pre><code># Install NGINX\nsudo apt update &amp;&amp; sudo apt install nginx -y\n\n# NGINX reverse proxy configuration\necho 'server {\n    listen 8084;\n\n    location / {\n        proxy_pass http://127.0.0.1:50750;\n        proxy_set_header Host localhost;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}' &gt; /home/vagrant/expose-linkerd\n\n# Create symlink of the NGINX configuration file\nsudo ln -s /home/vagrant/expose-linkerd /etc/nginx/sites-enabled/\n\n# Commit the reverse proxy configurations\nsudo systemctl restart nginx\n\n# Enable start on login\necho \"linkerd viz dashboard &amp;\" &gt;&gt; .profile\n\n# Start dashboard\nlinkerd viz dashboard &amp;\n\necho \"Linkerd Viz dashboard running!\"\n</code></pre>","text":""},{"location":"deployment_guide/deployment_guide/#12-install-microk8s","title":"1.2. Install MicroK8s","text":"<p>This section describes how to deploy the MicroK8s Kubernetes platform and configure it to be used with ETSI TeraFlowSDN controller. Besides, Docker is installed to build docker images for the ETSI TeraFlowSDN controller.</p> <p>The steps described in this section might take some minutes depending on your internet connection speed and the resources assigned to your VM, or the specifications of your physical server.</p> <p>To facilitate work, these steps are easier to be executed through an SSH connection, for instance using tools like PuTTY or MobaXterm.</p> Upgrade the Ubuntu distribution <p> Skip this step if you already did it during the creation of the VM.</p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> Install prerequisites <p></p> <pre><code>sudo apt-get install -y ca-certificates curl gnupg lsb-release snapd jq\n</code></pre> Install Docker CE <p> Install Docker CE and Docker BuildX plugin</p> <pre><code>sudo apt-get install -y docker.io docker-buildx\n</code></pre> <p>NOTE: Starting from Docker v23, Build architecture has been updated and <code>docker build</code> command entered into deprecation process in favor of the new <code>docker buildx build</code> command. Package <code>docker-buildx</code> provides the new <code>docker buildx build</code> command.</p> <p>Add key \"insecure-registries\" with the private repository to the daemon configuration. It is done in two commands since sometimes read from and write to same file might cause trouble.</p> <pre><code>if [ -s /etc/docker/daemon.json ]; then cat /etc/docker/daemon.json; else echo '{}'; fi \\\n    | jq 'if has(\"insecure-registries\") then . else .+ {\"insecure-registries\": []} end' -- \\\n    | jq '.\"insecure-registries\" |= (.+ [\"localhost:32000\"] | unique)' -- \\\n    | tee tmp.daemon.json\nsudo mv tmp.daemon.json /etc/docker/daemon.json\nsudo chown root:root /etc/docker/daemon.json\nsudo chmod 600 /etc/docker/daemon.json\n</code></pre> <p>Restart the Docker daemon</p> <pre><code>sudo systemctl restart docker\n</code></pre> Install MicroK8s <p></p> <p>Important: Some TeraFlowSDN dependencies need to be executed on top of MicroK8s/Kubernetes v1.24. It is not guaranteed (by now) to run on newer versions.</p> <pre><code># Install MicroK8s\nsudo snap install microk8s --classic --channel=1.24/stable\n\n# Create alias for command \"microk8s.kubectl\" to be usable as \"kubectl\"\nsudo snap alias microk8s.kubectl kubectl\n</code></pre> <p>It is important to make sure that <code>ufw</code> will not interfere with the internal pod-to-pod and pod-to-Internet traffic. To do so, first check the status. If <code>ufw</code> is active, use the following command to enable the communication.</p> <pre><code>\n# Verify status of ufw firewall\nsudo ufw status\n\n# If ufw is active, install following rules to enable access pod-to-pod and pod-to-internet\nsudo ufw allow in on cni0 &amp;&amp; sudo ufw allow out on cni0\nsudo ufw default allow routed\n</code></pre> <p>NOTE: MicroK8s can be used to compose a Highly Available Kubernetes cluster enabling you to construct an environment combining the CPU, RAM and storage resources of multiple machines. If you are interested in this procedure, review the official instructions in How to build a highly available Kubernetes cluster with MicroK8s, in particular, the step Create a MicroK8s multi-node cluster.</p> <p>References:</p> <ul> <li>The lightweight Kubernetes &gt; Install MicroK8s</li> <li>Install a local Kubernetes with MicroK8s</li> <li>How to build a highly available Kubernetes cluster with MicroK8s</li> </ul> Add user to the docker and microk8s groups <p></p> <p>It is important that your user has the permission to run <code>docker</code> and <code>microk8s</code> in the  terminal. To allow this, you need to add your user to the <code>docker</code> and <code>microk8s</code> groups with the  following commands:</p> <pre><code>sudo usermod -a -G docker $USER\nsudo usermod -a -G microk8s $USER\nsudo chown -f -R $USER $HOME/.kube\nsudo reboot\n</code></pre> <p>In case that you get trouble executing the following commands, might due to the .kube folder is not automatically provisioned into your home folder, you may follow the steps below:</p> <pre><code>mkdir -p $HOME/.kube\nsudo chown -f -R $USER $HOME/.kube\nmicrok8s config &gt; $HOME/.kube/config\nsudo reboot\n</code></pre> Check status of Kubernetes and addons <p> To retrieve the status of Kubernetes once, run the following command:</p> <pre><code>microk8s.status --wait-ready\n</code></pre> <p>To retrieve the status of Kubernetes periodically (e.g., every 1 second), run the  following command:</p> <pre><code>watch -n 1 microk8s.status --wait-ready\n</code></pre> Check all resources in Kubernetes <p> To retrieve the status of the Kubernetes resources once, run the following command:</p> <pre><code>kubectl get all --all-namespaces\n</code></pre> <p>To retrieve the status of the Kubernetes resources periodically (e.g., every 1  second), run the following command:</p> <pre><code>watch -n 1 kubectl get all --all-namespaces\n</code></pre> Enable addons <p></p> <p>First, we need to enable the community plugins (maintained by third parties):</p> <pre><code>microk8s.enable community\n</code></pre> <p>The Addons to be enabled are:</p> <ul> <li><code>dns</code>: enables resolving the pods and services by name</li> <li><code>helm3</code>: required to install NATS</li> <li><code>hostpath-storage</code>: enables providing storage for the pods (required by <code>registry</code>)</li> <li><code>ingress</code>: deploys an ingress controller to expose the microservices outside Kubernetes</li> <li><code>registry</code>: deploys a private registry for the TFS controller images</li> <li><code>linkerd</code>: deploys the linkerd service mesh used for load balancing among replicas</li> <li><code>prometheus</code>: set of tools that enable TFS observability through per-component instrumentation</li> <li><code>metrics-server</code>: deploys the Kubernetes metrics server for API access to service metrics</li> </ul> <pre><code>microk8s.enable dns helm3 hostpath-storage ingress registry prometheus metrics-server linkerd\n</code></pre> <p>Important: Enabling some of the addons might take few minutes. Do not proceed with next steps until the addons are ready. Otherwise, the deployment might fail. To confirm everything is up and running:</p> <ol> <li>Periodically    Check the status of Kubernetes    until you see the addons [dns, ha-cluster, helm3, hostpath-storage, ingress, linkerd, metrics-server, prometheus, registry, storage] in the enabled block.</li> <li>Periodically    Check Kubernetes resources    until all pods are Ready and Running.</li> <li>If it takes too long for the Pods to be ready, we observed that rebooting the machine may help.</li> </ol> <p>Then, create aliases to make the commands easier to access:</p> <pre><code>sudo snap alias microk8s.helm3 helm3\nsudo snap alias microk8s.linkerd linkerd\n</code></pre> <p>To validate that <code>linkerd</code> is working correctly, run:</p> <pre><code>linkerd check\n</code></pre> <p>To validate that the <code>metrics-server</code> is working correctly, run:</p> <pre><code>kubectl top pods --all-namespaces\n</code></pre> <p>and you should see a screen similar to the <code>top</code> command in Linux, showing the columns namespace, pod name, CPU (cores), and MEMORY (bytes).</p> <p>In case pods are not starting, check information from pods logs. For example, linkerd is sensitive for proper /etc/resolv.conf syntax.</p> <pre><code>kubectl logs &lt;podname&gt; --namespace &lt;namespace&gt;\n</code></pre> <p>If the command shows an error message, also restarting the machine might help.</p> Stop, Restart, and Redeploy <p> Find below some additional commands you might need while you work with MicroK8s:</p> <pre><code>microk8s.stop  # stop MicroK8s cluster (for instance, before power off your computer)\nmicrok8s.start # start MicroK8s cluster\nmicrok8s.reset # reset infrastructure to a clean state\n</code></pre> <p>If the following commands does not work to recover the MicroK8s cluster, you can redeploy it.</p> <p>If you want to keep MicroK8s configuration, use:</p> <pre><code>sudo snap remove microk8s\n</code></pre> <p>If you need to completely drop MicroK8s and its complete configuration, use:</p> <pre><code>sudo snap remove microk8s --purge\nsudo apt-get remove --purge docker.io docker-buildx\n</code></pre> <p>IMPORTANT: After uninstalling MicroK8s, it is convenient to reboot the computer (the VM if you work on a VM, or the physical computer if you use a physical computer). Otherwise, there are system configurations that are not correctly cleaned. Especially in what port forwarding and firewall rules matters.</p> <p>After the reboot, redeploy as it is described in this section.</p>"},{"location":"deployment_guide/deployment_guide/#13-deploy-teraflowsdn","title":"1.3. Deploy TeraFlowSDN","text":"<p>This section describes how to deploy TeraFlowSDN controller on top of MicroK8s using the environment configured in the previous sections.</p> Install prerequisites <p></p> <pre><code>sudo apt-get install -y git curl jq\n</code></pre> Clone the Git repository of the TeraFlowSDN controller <p> Clone from ETSI-hosted GitLab code repository:</p> <pre><code>mkdir ~/tfs-ctrl\ngit clone https://labs.etsi.org/rep/tfs/controller.git ~/tfs-ctrl\n</code></pre> <p>Important: The original H2020-TeraFlow project hosted on GitLab.com has been  archieved and will not receive further contributions/updates. Please, clone from ETSI-hosted GitLab code repository.</p> Checkout the appropriate Git branch <p> TeraFlowSDN controller versions can be found in the appropriate release tags and/or branches as described in Home &gt; Versions.</p> <p>By default the branch master is checked out and points to the latest stable version of the TeraFlowSDN controller, while branch develop contains the latest developments and contributions under test and validation.</p> <p>To switch to the appropriate branch run the following command, changing <code>develop</code> by the name of the branch you want to deploy:</p> <pre><code>cd ~/tfs-ctrl\ngit checkout develop\n</code></pre> Prepare a deployment script with the deployment settings <p> Create a new deployment script, e.g., <code>my_deploy.sh</code>, adding the appropriate settings as  follows. This section provides just an overview of the available settings. An example <code>my_deploy.sh</code> script is provided in the root folder of the project for your convenience with full description of all the settings.</p> <p>Note: The example <code>my_deploy.sh</code> script provides reasonable settings for deploying a functional and complete enough TeraFlowSDN controller, and a brief description of their meaning. To see extended descriptions, check scripts in the <code>deploy</code> folder.</p> <pre><code>cd ~/tfs-ctrl\ntee my_deploy.sh &gt;/dev/null &lt;&lt; EOF\n# ----- TeraFlowSDN ------------------------------------------------------------\nexport TFS_REGISTRY_IMAGES=\"http://localhost:32000/tfs/\"\nexport TFS_COMPONENTS=\"context device ztp monitoring pathcomp service slice nbi webui load_generator\"\nexport TFS_IMAGE_TAG=\"dev\"\nexport TFS_K8S_NAMESPACE=\"tfs\"\nexport TFS_EXTRA_MANIFESTS=\"manifests/nginx_ingress_http.yaml\"\nexport TFS_GRAFANA_PASSWORD=\"admin123+\"\nexport TFS_SKIP_BUILD=\"\"\n\n# ----- CockroachDB ------------------------------------------------------------\nexport CRDB_NAMESPACE=\"crdb\"\nexport CRDB_EXT_PORT_SQL=\"26257\"\nexport CRDB_EXT_PORT_HTTP=\"8081\"\nexport CRDB_USERNAME=\"tfs\"\nexport CRDB_PASSWORD=\"tfs123\"\nexport CRDB_DATABASE=\"tfs\"\nexport CRDB_DEPLOY_MODE=\"single\"\nexport CRDB_DROP_DATABASE_IF_EXISTS=\"YES\"\nexport CRDB_REDEPLOY=\"\"\n\n# ----- NATS -------------------------------------------------------------------\nexport NATS_NAMESPACE=\"nats\"\nexport NATS_EXT_PORT_CLIENT=\"4222\"\nexport NATS_EXT_PORT_HTTP=\"8222\"\nexport NATS_REDEPLOY=\"\"\n\n# ----- QuestDB ----------------------------------------------------------------\nexport QDB_NAMESPACE=\"qdb\"\nexport QDB_EXT_PORT_SQL=\"8812\"\nexport QDB_EXT_PORT_ILP=\"9009\"\nexport QDB_EXT_PORT_HTTP=\"9000\"\nexport QDB_USERNAME=\"admin\"\nexport QDB_PASSWORD=\"quest\"\nexport QDB_TABLE_MONITORING_KPIS=\"tfs_monitoring_kpis\"\nexport QDB_TABLE_SLICE_GROUPS=\"tfs_slice_groups\"\nexport QDB_DROP_TABLES_IF_EXIST=\"YES\"\nexport QDB_REDEPLOY=\"\"\n\nEOF\n</code></pre> <p>The settings are organized in 4 sections: - Section <code>TeraFlowSDN</code>:   - <code>TFS_REGISTRY_IMAGE</code> enables to specify the private Docker registry to be used, by default, we assume to use the Docker respository enabled in MicroK8s.   - <code>TFS_COMPONENTS</code> specifies the components their Docker image will be rebuilt, uploaded to the private Docker registry, and deployed in Kubernetes.   - <code>TFS_IMAGE_TAG</code> defines the tag to be used for Docker images being rebuilt and uploaded to the private Docker registry.   - <code>TFS_K8S_NAMESPACE</code> specifies the name of the Kubernetes namespace to be used for deploying the TFS components.   - <code>TFS_EXTRA_MANIFESTS</code> enables to provide additional manifests to be applied into the Kubernetes environment during the deployment. Typical use case is to deploy ingress controllers, service monitors for Prometheus, etc.   - <code>TFS_GRAFANA_PASSWORD</code> lets you specify the password you want to use for the <code>admin</code> user of the Grafana instance being deployed and linked to the Monitoring component.   - <code>TFS_SKIP_BUILD</code>, if set to <code>YES</code>, prevents rebuilding the Docker images. That means, the deploy script will redeploy existing Docker images without rebuilding/updating them.</p> <ul> <li>Section <code>CockroachDB</code>: enables to configure the deployment of the backend CockroachDB database.</li> <li> <p>Check example script <code>my_deploy.sh</code> for further details.</p> </li> <li> <p>Section <code>NATS</code>: enables to configure the deployment of the backend NATS message broker.</p> </li> <li> <p>Check example script <code>my_deploy.sh</code> for further details.</p> </li> <li> <p>Section <code>QuestDB</code>: enables to configure the deployment of the backend QuestDB timeseries database.</p> </li> <li>Check example script <code>my_deploy.sh</code> for further details.</li> </ul> Confirm that MicroK8s is running <p></p> <p>Run the following command:</p> <pre><code>microk8s status\n</code></pre> <p>If it is reported <code>microk8s is not running, try microk8s start</code>, run the following command to start MicroK8s:</p> <pre><code>microk8s start\n</code></pre> <p>Confirm everything is up and running:</p> <ol> <li>Periodically Check the status of Kubernetes until you see the addons [dns, ha-cluster, helm3, hostpath-storage, ingress, registry, storage] in the enabled block.</li> <li>Periodically Check Kubernetes resources until all pods are Ready and Running.</li> </ol> Deploy TFS controller <p> First, source the deployment settings defined in the previous section. This way, you do not need to specify the environment variables in each and every command you execute to operate the TFS controller. Be aware to re-source the file if you open new terminal sessions. Then, run the following command to deploy TeraFlowSDN controller on top of the MicroK8s Kubernetes platform.</p> <pre><code>cd ~/tfs-ctrl\nsource my_deploy.sh\n./deploy/all.sh\n</code></pre> <p>The script performs the following steps:</p> <ul> <li>Executes script <code>./deploy/crdb.sh</code> to automate deployment of CockroachDB database used by Context component.</li> <li>The script automatically checks if CockroachDB is already deployed.</li> <li>If there are settings instructing to drop the database and/or redeploy CockroachDB, it does the appropriate actions to honor them as defined in previous section.</li> <li>Executes script <code>./deploy/nats.sh</code> to automate deployment of NATS message broker used by Context component.</li> <li>The script automatically checks if NATS is already deployed.</li> <li>If there are settings instructing to redeploy the message broker, it does the appropriate actions to honor them as defined in previous section.</li> <li>Executes script <code>./deploy/qdb.sh</code> to automate deployment of QuestDB timeseries database used by Monitoring component.</li> <li>The script automatically checks if QuestDB is already deployed.</li> <li>If there are settings instructing to redeploy the timeseries database, it does the appropriate actions to honor them as defined in previous section.</li> <li>Executes script <code>./deploy/tfs.sh</code> to automate deployment of TeraFlowSDN.</li> <li>Creates the namespace defined in <code>TFS_K8S_NAMESPACE</code></li> <li>Creates secrets for CockroachDB, NATS, and QuestDB to be used by Context and Monitoring components.</li> <li>Builds the Docker images for the components defined in <code>TFS_COMPONENTS</code></li> <li>Tags the Docker images with the value of <code>TFS_IMAGE_TAG</code></li> <li>Pushes the Docker images to the repository defined in <code>TFS_REGISTRY_IMAGE</code></li> <li>Deploys the components defined in <code>TFS_COMPONENTS</code></li> <li>Creates the file <code>tfs_runtime_env_vars.sh</code> with the environment variables for the components defined in <code>TFS_COMPONENTS</code> defining their local host addresses and their port numbers.</li> <li>Applies extra manifests defined in <code>TFS_EXTRA_MANIFESTS</code> such as:<ul> <li>Creating an ingress controller listening at port 80 for HTTP connections to enable external access to the TeraFlowSDN WebUI, Grafana Dashboards, and Compute NBI interfaces.</li> <li>Deploying service monitors to enable monitoring the performance of the components, device drivers and service handlers.</li> </ul> </li> <li>Initialize and configure the Grafana dashboards (if Monitoring component is deployed)</li> <li>Report a summary of the deployment</li> <li>See Show Deployment and Logs</li> </ul>"},{"location":"deployment_guide/deployment_guide/#14-webui-and-grafana-dashboards","title":"1.4. WebUI and Grafana Dashboards","text":"<p>This section describes how to get access to the TeraFlowSDN controller WebUI and the monitoring Grafana dashboards.</p> Access the TeraFlowSDN WebUI <p> If you followed the installation steps based on MicroK8s, you got an ingress controller installed that exposes on TCP port 80.</p> <p>Besides, the ingress controller defines the following reverse proxy paths (on your local machine):</p> <ul> <li><code>http://127.0.0.1/webui</code>: points to the WebUI of TeraFlowSDN.</li> <li><code>http://127.0.0.1/grafana</code>: points to the Grafana dashboards.   This endpoint brings access to the monitoring dashboards of TeraFlowSDN.   The credentials for the <code>admin</code>user are those defined in the <code>my_deploy.sh</code> script, in the <code>TFS_GRAFANA_PASSWORD</code> variable.</li> <li><code>http://127.0.0.1/restconf</code>: points to the Compute component NBI based on RestCONF.    This endpoint enables connecting external software, such as ETSI OpenSourceMANO NFV Orchestrator, to TeraFlowSDN.</li> </ul> <p>Note: In the creation of the VM, a forward from host TCP port 8080 to VM's TCP port 80 is configured, so the WebUIs and REST APIs of TeraFlowSDN should be exposed on the endpoint <code>127.0.0.1:8080</code> of your local machine instead of <code>127.0.0.1:80</code>.</p>"},{"location":"deployment_guide/deployment_guide/#15-show-deployment-and-logs","title":"1.5. Show Deployment and Logs","text":"<p>This section presents some helper scripts to inspect the status of the deployment and  the logs of the components. These scripts are particularly helpful for troubleshooting during execution of  experiments, development, and debugging.</p> Report the deployment of the TFS controller <p></p> <p>The summary report given at the end of the Deploy TFS controller procedure can be generated manually at any time by running the following command. You can avoid sourcing <code>my_deploy.sh</code> if it has been already done.</p> <pre><code>cd ~/tfs-ctrl\nsource my_deploy.sh\n./deploy/show.sh\n</code></pre> <p>Use this script to validate that all the pods, deployments, replica sets, ingress  controller, etc. are ready and have the appropriate state, e.g., running for Pods, and  the services are deployed and have appropriate IP addresses and port numbers.</p> Report the log of a specific TFS controller component <p></p> <p>A number of scripts are pre-created in the <code>scripts</code> folder to facilitate the inspection  of the component logs. For instance, to dump the log of the Context component, run the following command. You can avoid sourcing <code>my_deploy.sh</code> if it has been already done.</p> <pre><code>source my_deploy.sh\n./scripts/show_logs_context.sh\n</code></pre>"},{"location":"development_guide/development_guide/","title":"2. Development Guide","text":""},{"location":"development_guide/development_guide/#21-configure-environment","title":"2.1. Configure Environment","text":""},{"location":"development_guide/development_guide/#211-python","title":"2.1.1. PythonUpgrade the Ubuntu distribution  <p>Skip this step if you already did it during the installation of your machine.</p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> Install PyEnv dependencies <p></p> <pre><code>sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget \\\n    curl llvm git libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev\n</code></pre> Install PyEnv <p></p> <p>We recommend installing PyEnv through PyEnv Installer. Below you can find the instructions, but we refer you to the link for updated  instructions.</p> <pre><code>curl https://pyenv.run | bash\n# When finished, edit ~/.bash_profile // ~/.profile // ~/.bashrc as the installer proposes.\n# In general, it means to append the following lines to ~/.bashrc:\nexport PYENV_ROOT=\"$HOME/.pyenv\"\ncommand -v pyenv &gt;/dev/null || export PATH=\"$PYENV_ROOT/bin:$PATH\"\neval \"$(pyenv init -)\"\neval \"$(pyenv virtualenv-init -)\"\n</code></pre> <p>In case .bashrc is not linked properly to your profile, you may need to append the  following line into your local .profile file:</p> <pre><code># Open ~/.profile and append this line:\n+source \"$HOME\"/.bashrc\n</code></pre> Restart the machine <p> Restart the machine for all the changes to take effect.</p> <pre><code>sudo reboot\n</code></pre> Install Python 3.9 over PyEnv <p></p> <p>ETSI TeraFlowSDN uses Python 3.9 by default. You should install the latest stable update of Python 3.9, i.e., avoid \"-dev\" versions. To find the latest version available in PyEnv, you can run the following command:</p> <pre><code>pyenv install --list | grep \" 3.9\"\n</code></pre> <p>At the time of writing, this command will output the following list:</p> <pre><code>  3.9.0\n  3.9-dev\n  3.9.1\n  3.9.2\n  3.9.4\n  3.9.5\n  3.9.6\n  3.9.7\n  3.9.8\n  3.9.9\n  3.9.10\n  3.9.11\n  3.9.12\n  3.9.13\n  3.9.14 \n  3.9.15\n  3.9.16 ** always select the latest version **\n</code></pre> <p>Therefore, the latest stable version is Python 3.9.16. To install this version, you should run:</p> <pre><code>pyenv install 3.9.16\n    # This command might take some minutes depending on your Internet connection speed \n    # and the performance of your machine.\n</code></pre> Create the Virtual Environment for TeraFlowSDN <p> The following commands create a virtual environment named as <code>tfs</code> using Python 3.9 and  associate that environment with the current folder, i.e., <code>~/tfs-ctrl</code>. That way, when you are in that folder, the associated virtual environment will be used,  thus inheriting the Python interpreter, i.e., Python 3.9, and the Python packages  installed on it.</p> <pre><code>cd ~/tfs-ctrl\npyenv virtualenv 3.9.16 tfs\npyenv local 3.9.16/envs/tfs\n</code></pre> <p>After completing these commands, you should see in your prompt that now you're within  the virtual environment <code>3.9.16/envs/tfs</code> on folder <code>~/tfs-ctrl</code>:</p> <pre><code>(3.9.16/envs/tfs) tfs@tfs-vm:~/tfs-ctrl$\n</code></pre> <p>In case that the correct pyenv does not get automatically activated when you change to  the tfs-ctrl/ folder, then execute the following command:</p> <pre><code>cd ~/tfs-ctrl\npyenv activate 3.9.16/envs/tfs\n</code></pre> Install the basic Python packages within the virtual environment <p> From within the <code>3.9.16/envs/tfs</code> environment on folder <code>~/tfs-ctrl</code>, run the following  commands to install the basic Python packages required to work with TeraFlowSDN.</p> <pre><code>cd ~/tfs-ctrl\n./install_requirements.sh\n</code></pre> <p>Some dependencies require to re-load the session, so log-out and log-in again.</p> Generate the Python code from the gRPC Proto messages and services <p></p> <p>The components, e.g., microservices, of the TeraFlowSDN controller, in general, use a gRPC-based open API to interoperate. All the protocol definitions can be found in sub-folder <code>proto</code> within the root project folder. For additional details on gRPC, visit the official web-page gRPC.</p> <p>In order to interact with the components, (re-)generate the Python code from gRPC definitions running the following command:</p> <pre><code>cd ~/tfs-ctrl\nproto/generate_code_python.sh\n</code></pre>","text":"<p>This section describes how to configure the Python environment to run experiments and  develop code for the ETSI TeraFlowSDN controller. In particular, we use PyEnv to install the appropriate  version of Python and manage the virtual environments.</p>"},{"location":"development_guide/development_guide/#212-java-quarkus","title":"2.1.2. Java (Quarkus) <p>This section describe the steps needed to create a development environment for TFS components implemented in Java. Currently, ZTP and Policy components have been developed in Java (version 11) and use the Quarkus framework, which enables kubernetes-native development.</p> Install JDK <p> To begin, make sure that you have java installed and in the correct version</p> <pre><code>java --version\n</code></pre> <p>If you don't have java installed you will get an error like the following:</p> <pre><code>Command 'java' not found, but can be installed with:\n\nsudo apt install default-jre              # version 2:1.11-72build1, or\nsudo apt install openjdk-11-jre-headless  # version 11.0.14+9-0ubuntu2\nsudo apt install openjdk-17-jre-headless  # version 17.0.2+8-1\nsudo apt install openjdk-18-jre-headless  # version 18~36ea-1\nsudo apt install openjdk-8-jre-headless   # version 8u312-b07-0ubuntu1\n</code></pre> <p>In which case you should use the following command to install the correct version:</p> <pre><code>sudo apt install openjdk-11-jre-headless\n</code></pre> <p>Else you should get something like the following:</p> <pre><code>openjdk 11.0.18 2023-01-17\nOpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1)\nOpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1, mixed mode, sharing)\n</code></pre> Compiling and testing existing components <p> In the root directory of the existing Java components you will find an executable maven wrapper named <code>mvnw</code>. You could use this executable, which is already configured in pair with the components, instead of your local maven installation. So for example if you want to compile the project you would run the following:</p> <pre><code>./mvnw compile\n</code></pre> VS Code Quarkus plugin <p> In case you are using VS Code for development, we suggest to install the official Quarkus extension. The extension should be able to automatically find the current open project and integrate with the above <code>mvnw</code> maven wrapper, making it easier to control the maven lifecycle. Make sure that you open the specific component directory (i.e., <code>src/ztp</code> or <code>src/policy</code>) and not the general controller one (i.e., <code>src</code>.</p> New Java TFS component <p></p> <p>Sample Project</p> <p>If you want to create a new TFS component written in Java you could generate a new Quarkus project based on the following project:</p> <p>TFS Sample Quarkus Project</p> <p>In that way, you should have most of the libraries you would need to integrate with the rest of the TFS Components. Feel free however to add or remove libraries depending on your needs.</p> <p>Initial setup</p> <p>If you used the sample project above, you should have a project with a basic structure. However there are some steps that you should take before starting development.</p> <p>First make sure that you copy the protobuff files, that are found in the root directory of the TFS SDN controller, to the <code>new-component/src/main/proto</code> directory.</p> <p>Next you should create the following files:</p> <ul> <li><code>new-component/.gitlab-ci.yml</code></li> <li><code>new-component/Dockerfile</code></li> <li><code>new-component/src/resources/application.yaml</code></li> </ul> <p>We suggest to copy the respective files from existing components (Automation and Policy) and change them according to your needs.</p>","text":""},{"location":"development_guide/development_guide/#213-java-maven","title":"2.1.3. Java (Maven) <p>Page under construction</p>","text":""},{"location":"development_guide/development_guide/#214-rust","title":"2.1.4. Rust <p>Page under construction</p>","text":""},{"location":"development_guide/development_guide/#215-erlang","title":"2.1.5. Erlang <p>This section describes how to configure the Erlang environment to run experiments and develop code for the ETSI TeraFlowSDN controller.</p> <p>First we need to install Erlang. There is multiple way, for development we will be using ASDF, a tool that allows the installation of multiple version of Erlang at the same time, and switch from one version to the other at will.</p> <ul> <li>First, install any missing dependencies:</li> </ul> <pre><code>sudo apt install curl git autoconf libncurses-dev build-essential m4 libssl-dev \n</code></pre> <ul> <li>Download ASDF tool to the local account:</li> </ul> <pre><code>git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.2\n</code></pre> <ul> <li>Make ASDF activate on login by adding these lines at the end of the <code>~/.bashrc</code> file:</li> </ul> <pre><code>. $HOME/.asdf/asdf.sh\n. $HOME/.asdf/completions/asdf.bash\n</code></pre> <ul> <li>Logout and log back in to activate ASDF.</li> </ul> <p>ASDF supports multiple tools by installing there corresponding plugins.</p> <ul> <li>Install ASDF plugin for Erlang:</li> </ul> <pre><code>asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git\n</code></pre> <ul> <li>Install a version of Erlang:</li> </ul> <pre><code>asdf install erlang 24.3.4.2\n</code></pre> <ul> <li>Activate Erlang locally for TFS controller. This will create a local file called <code>.tool-versions</code> defining which version of the tools to use when running under the current directory:</li> </ul> <pre><code>cd tfs-ctrl/\nasdf local erlang 24.3.4.2\n</code></pre> <p>Erlang projects uses a build tool called rebar3. It is used to manager project dependenecies, compile a project and generate project releases.</p> <ul> <li>Install rebar3 localy from source:</li> </ul> <pre><code>cd ~\ngit clone https://github.com/erlang/rebar3.git\ncd rebar3\nasdf local erlang 24.3.4.2\n./bootstrap\n./rebar3 local install\n</code></pre> <ul> <li>Update <code>~/.bashrc</code> to use rebar3 by adding this line at the end:</li> </ul> <pre><code>export PATH=$HOME/.cache/rebar3/bin:$PATH\n</code></pre> <ul> <li>Logout and log back in.</li> </ul>","text":""},{"location":"development_guide/development_guide/#216-kotlin","title":"2.1.6. Kotlin <p>This section describes the steps needed to establish a development environment for TFS (TeraFlowSDN) components implemented in Kotlin. Currently, the <code>Gateway</code> component stands as the sole component developed in Kotlin.</p> Install Kotlin <p> To begin, make sure that you have kotlin installed and its current version:</p> <pre><code>kotlin -version\n</code></pre> <p>If you don't have kotlin installed you will get an error like the following:</p> <pre><code>Command 'kotlin' not found, but can be installed with:\nsudo snap install --classic kotlin\n</code></pre> <p>In which case you should use the following command to install the correct version:</p> <pre><code> sudo snap install --classic kotlin\n</code></pre> <p>Currently, the recommended version is 1.6.21, which uses Java Runtime Environment (JRE) version 11.</p> Compiling and testing existing components <p> To compile a Kotlin project using Gradle, similarly to using the Maven wrapper (mvnw) for Java projects, you can use the Gradle wrapper (gradlew) within the root directory of your Kotlin component, specifically the gateway directory.</p> <p>Navigate to the gateway directory within your Kotlin project. Ensure that it contains the gradlew script along with the gradle directory. Then, create a directory named <code>proto</code> and move all the files with extension <code>.proto</code> in this way:</p> <pre><code>mkdir proto\ncp ../../../proto/*.proto ./proto \n</code></pre> <p>For building the application, open a terminal or command prompt, navigate to the gateway directory, and run the following command:</p> <pre><code>./gradlew build\n</code></pre> <p>The following program runs the gateway application:</p> <pre><code>./gradlew runServer \n</code></pre> New Kotlin TFS component <p></p> <p>Sample Project</p> <p>If you want to create a new TFS component written in Kotlin you could generate a Kotlin project using <code>gradle</code>. The recommended version is 7.1. Follow the following Gradle guide for its installation. For building the prokect follow this link instead.</p> <p>From inside the new project directory, run the init task using the following command in a terminal: <code>gradle init</code>. </p> <p>The output will look like this:</p> <pre><code>$ gradle init\n\nSelect type of project to generate:\n  1: basic\n  2: application\n  3: library\n  4: Gradle plugin\nEnter selection (default: basic) [1..4] 2\n\nSelect implementation language:\n  1: C++\n  2: Groovy\n  3: Java\n  4: Kotlin\n  5: Scala\n  6: Swift\nEnter selection (default: Java) [1..6] 4\n\nSelect build script DSL:\n  1: Groovy\n  2: Kotlin\nEnter selection (default: Groovy) [1..2] 1\n\nProject name (default: demo):\nSource package (default: demo):\n\n\nBUILD SUCCESSFUL\n2 actionable tasks: 2 executed\n</code></pre> <p>Initial setup</p> <p>The <code>gradle init</code> command generates the new project. </p> <p>First, ensure the protobuf files are copied from the root directory of the TFS SDN controller. Run the following command in the directory of the new project:</p> <pre><code>mkdir proto \ncp TFS/project/root/path/proto/*.proto ./proto/\n</code></pre> <p>The file <code>build.gradle.ktl</code> is fundamental as it manages dependencies. Adjust it for adding external libraries.  </p> <p>Next you should create the following files:</p> <ol> <li><code>new-component/.gitlab-ci.yml</code></li> <li><code>new-component/Dockerfile</code></li> </ol> <p>We recommend leveraging the structures and configurations found in the files of existing components for inspiration.</p> <p>Docker Container This project operates with Docker containers. Ensure the production of the container version for your component. To generate the container version of the project, modify the 'new-component/Dockerfile.' Execute the following command from the project's root directory:</p> <pre><code>docker build -t new-image -f new-component/Dockerfile ./\n</code></pre>","text":""},{"location":"development_guide/development_guide/#22-configure-vscode","title":"2.2. Configure VScode","text":"Install VSCode and the required extensions <p>If not already done, install VSCode and the \"Remote SSH\" extension on your local machine, not in the VM.</p> <p>Note: \"Python\" extension is not required here. It will be installed later on the VSCode server running on the VM.</p> Configure the \"Remote SSH\" extension <p></p> <ul> <li>Go to left icon \"Remote Explorer\"</li> <li>Click the \"gear\" icon next to \"SSH TARGETS\" on top of \"Remote Explorer\" bar</li> <li>Choose to edit \"&lt;...&gt;/.ssh/config\" file (or equivalent)</li> <li>Add the following entry (assuming previous port forwarding configuration):</li> </ul> <pre><code>Host TFS-VM\n    HostName 127.0.0.1\n    Port 2200\n    ForwardX11 no\n    User tfs\n</code></pre> <ul> <li>Save the file</li> <li>An entry \"TFS-VM\" should appear on \"SSH TARGETS\".</li> </ul> Connect VSCode to the VM through \"Remote SSH\" extension <p></p> <ul> <li>Right-click on \"TFS-VM\"</li> <li>Select \"Connect to Host in Current Window\"</li> <li>Reply to the questions asked</li> <li>Platform of the remote host \"TFS-VM\": Linux</li> <li>\"TFS-VM\" has fingerprint \"\". Do you want to continue?: Continue <li>Type tfs user's password: tfs123</li> <li>You should be now connected to the TFS-VM.</li> <p>Note: if you get a connection error message, the reason might be due to wrong SSH server fingerprint. Edit file           \"&lt;...&gt;/.ssh/known_hosts\" on your local user account, check if there is a line starting with           \"[127.0.0.1]:2200\" (assuming previous port forwarding configuration), remove the entire line, save the file,           and retry connection.</p> Add SSH key to prevent typing the password every time <p> This step creates an SSH key in the VM and installs it on the VSCode to prevent having to type the password every time.</p> <ul> <li>In VSCode (connected to the VM), click menu \"Terminal &gt; New Terminal\"</li> <li>Run the following commands on the VM's terminal through VSCode</li> </ul> <pre><code>ssh-keygen -t rsa -b 4096 -f ~/.ssh/tfs-vm.key\n  # leave password empty\nssh-copy-id -i ~/.ssh/tfs-vm.key.pub tfs@10.0.2.10\n  # tfs@10.0.2.10's password: &lt;type tfs user's password: tfs123&gt;\nrm .ssh/known_hosts \n</code></pre> <ul> <li>In VSCode, click left \"Explorer\" panel to expand, if not expanded, and click \"Open Folder\" button.</li> <li>Choose \"/home/tfs/\"</li> <li>Type tfs user's password when asked</li> <li>Trust authors of the \"/home/tfs [SSH: TFS-VM]\" folder when asked</li> <li>Right click on the file \"tfs-vm.key\" in the file explorer</li> <li>Select \"Download...\" option</li> <li>Download the file into your user's accout \".ssh\" folder</li> <li> <p>Delete files \"tfs-vm.key\" and \"tfs-vm.key.pub\" on the TFS-VM.</p> </li> <li> <p>In VSCode, click left \"Remote Explorer\" panel to expand</p> </li> <li>Click the \"gear\" icon next to \"SSH TARGETS\" on top of \"Remote Explorer\" bar</li> <li>Choose to edit \"&lt;...&gt;/.ssh/config\" file (or equivalent)</li> <li>Find entry \"Host TFS-VM\" and update it as follows:</li> </ul> <pre><code>Host TFS-VM\n    HostName 127.0.0.1\n    Port 2200\n    ForwardX11 no\n    User tfs\n    IdentityFile \"&lt;path to the downloaded identity private key file&gt;\"\n</code></pre> <ul> <li>Save the file</li> <li>From now, VSCode will use the identity file to connect to the TFS-VM instead of the user's password.</li> </ul> Install VSCode Python Extension (in VSCode server) <p> This step installs Python extensions in VSCode server running in the VM.</p> <ul> <li>In VSCode (connected to the VM), click left button \"Extensions\"</li> <li>Search \"Python\" extension in the extension Marketplace.</li> <li> <p>Install official \"Python\" extension released by Microsoft.</p> <ul> <li>By default, since you're connected to the VM, it will be installed in the VSCode server running in the VM.</li> </ul> </li> <li> <p>In VSCode (connected to the VM), click left button \"Explorer\"</p> </li> <li>Click \"Ctrl+Alt+P\" and type \"Python: Select Interpreter\". Select option \"Python: 3.9.13 64-bit ('tfs')\"</li> </ul> Define environment variables for VSCode <p> The source code in the TFS controller project is hosted in folder <code>src/</code>. To help VSCode find the Python modules and packages, add the following file into your working space root folder:</p> <pre><code>echo \"PYTHONPATH=./src\" &gt;&gt; ~/tfs-ctrl/.env\n</code></pre>"},{"location":"development_guide/development_guide/#23-develop-a-component-wip","title":"2.3. Develop A Component (WIP)","text":"<p>Page under construction</p>"},{"location":"testing/postman/","title":"Postman","text":"<p>In this section we can use Postman to publish an API as a provider and use it as an invoker.</p>"},{"location":"testing/postman/#requisites","title":"Requisites","text":"<ul> <li>We will need to have Node.js installed since we will use a small script to create the CSRs of the certificates.</li> <li>An instance of CAPIF (If it is not local, certain variables would have to be modified both in the Node.js script and in the Postman environment variables).</li> </ul>"},{"location":"testing/postman/#first-steps","title":"First steps","text":"<ol> <li>Install the Node dependencies package.json to run the script with:</li> </ol> <pre><code>npm i\n</code></pre> <ol> <li>Run the script.js with the following command:</li> </ol> <pre><code>node script.js\n</code></pre> <ol> <li>Import Postman collection and environment variables (CAPIF.postman_collection.json and CAPIF.postman_environment.json)</li> <li>Select CAPIF Environment before start testing.</li> </ol>"},{"location":"testing/postman/#remote-capif","title":"Remote CAPIF","text":"<p>If the CAPIF is not local, the host and port of both the CAPIF and the register would have to be specified in the variables, and the CAPIF_HOSTNAME in the script, necessary to obtain the server certificate.</p> <p>Enviroments in Postman</p> <pre><code>CAPIF_HOSTNAME     capifcore\nCAPIF_PORT         8080\nREGISTER_HOSTNAME  register\nREGISTER_PORT      8084\n</code></pre> <p>Const in script.js</p> <pre><code>CAPIF_HOSTNAME    capifcore\n</code></pre>"},{"location":"testing/postman/#capif-flows","title":"CAPIF Flows","text":"<p>Once the first steps have been taken, we can now use Postman requests. These requests are numbered in the order that must be followed to obtain everything necessary from CAPIF.</p>"},{"location":"testing/postman/#creation-of-user-by-admin","title":"Creation of User by Admin","text":"<p>The first step would be for an administrator to create a user with which a provider and an invoker will be created. To do this, the admin must log in to obtain the token needed in admin requests.</p>"},{"location":"testing/postman/#01-login_admin","title":"01-Login_admin","text":""},{"location":"testing/postman/#02-creation-of-user","title":"02-Creation of User","text":""},{"location":"testing/postman/#publication-of-an-api","title":"Publication of an API","text":"<p>The next step is to register a provider using the user created by the administrator in order to publish an API.</p>"},{"location":"testing/postman/#03-getauth_provider","title":"03-getauth_provider","text":""},{"location":"testing/postman/#04-onboard_provider","title":"04-onboard_provider","text":"<p>At this point we move on to using certificate authentication in CAPIF. In Postman it is necessary to add the certificates manually and using more than one certificate for the same host as we do in CAPIF complicates things. For this reason, we use the script to overwrite a certificate and a key when it is necessary to have a specific one.</p> <p>To configure go to settings in Postman and open the certificates section. </p> <ul> <li>Here, activate the CA certificates option and add the ca_cert.pem file found in the Responses folder.</li> <li>Adds a client certificate specifying the CAPIF host being used and the files client_cert.crt and client_key.key in the Responses folder.</li> </ul> <p>Once this is done, the node script will be in charge of changing the certificate that is necessary in each request.</p>"},{"location":"testing/postman/#05-publish_api","title":"05-publish_api","text":"<p>Once the api is published, we can start it. In this case we have a test one created in python called hello_api.py that can be executed with the following command:</p> <pre><code>python3 hello_api.py\n</code></pre> <p>The API publication interface is set to localhost with port 8088, so the service must be set up locally. If you wanted to build it on another site, you would have to change the interface description in the body of publish_api.</p> <p>With this the provider part would be finished.</p>"},{"location":"testing/postman/#calling-the-api","title":"Calling the API","text":"<p>Finally, we will create an invoker with the user given by the administrator to be able to use the published api.</p>"},{"location":"testing/postman/#06-getauth_invoker","title":"06-getauth_invoker","text":""},{"location":"testing/postman/#07-onboard_invoker","title":"07-onboard_invoker","text":"<p>At this point we move on to using certificate authentication in CAPIF. If you did not configure the provider's certificates, you would have to do it now.</p>"},{"location":"testing/postman/#08-discover","title":"08-discover","text":""},{"location":"testing/postman/#09-security_context","title":"09-security_context","text":""},{"location":"testing/postman/#10-get_token","title":"10-get_token","text":""},{"location":"testing/postman/#11-call_service","title":"11-call_service","text":"<p>With this, we would have made the API call and finished the flow.</p>"},{"location":"testing/postman/#other-requests","title":"Other requests","text":"<p>Other requests that we have added are the following:</p> <ul> <li>offboard_provider      Performs offboarding of the provider, thereby eliminating the published APIs.</li> <li>offboard_invoker       Offboards the invoker, also eliminating access to the APIs of that invoker.</li> <li>remove_user            Delete the user.</li> <li>refresh_admin_token    Return a new access token to the admin.</li> </ul>"},{"location":"testing/postman/#notes","title":"Notes","text":"<ul> <li>This process is designed to teach how requests are made in Postman and the flow that should be followed to publish and use an API.</li> <li>It is possible that if external CAPIFs are used (Public CAPIF) the test data may already be used or the API already registered.</li> <li>It is necessary to have the Node service running to make the certificate change for the requests, otherwise it will not work.</li> <li>We are working on adding more requests to the Postman collection.</li> <li>This collection is a testing guide and is recommended for testing purposes only.</li> </ul>"},{"location":"testing/robotframework/","title":"Robot Framework","text":""},{"location":"testing/robotframework/#steps-to-test","title":"Steps to Test","text":"<p>To run any test locally you will need docker and docker-compose installed in order run services and execute test plan. Steps will be:</p> <ul> <li> <p>Run All Services: See section Run All CAPIF Services</p> </li> <li> <p>Run desired tests: At this point we have 2 options:</p> </li> <li> <p>Using helper script: Script Test Execution</p> </li> <li>Build robot docker image and execute manually robot docker: Manual Build And Test Execution</li> </ul>"},{"location":"testing/robotframework/#script-test-execution","title":"Script Test Execution","text":"<p>This script will build robot docker image if it's need and execute tests selected by \"include\" option. Just go to service folder, execute and follow steps.</p> <pre><code>./run_capif_tests.sh --include &lt;TAG&gt;\n</code></pre> <p>Results will be stored at /results <p>Please check parameters (include) under Test Execution at Manual Build And Test Execution.</p>"},{"location":"testing/robotframework/#mock-server","title":"Mock Server","text":"<p>Some tests on Test Plans require mockserver. That mock server must be deployed and reachable by Robot Framework and CCF under test.</p> <p>To run Mock Server locally you can just execute the next script:</p> <pre><code>cd services\n./run_mock_server.sh\n\nor\n./run.sh -s\n</code></pre> <p>If you want to launch only tests that not needed mockserver, just add \"--exclude mockserver\" parameter to robot execution:</p> <pre><code>./run_capif_tests.sh --include &lt;TAG&gt; --exclude mockserver\n</code></pre> <p>After run tests the Mock Server can be removed from local deployment:</p> <pre><code>./clean_mock_server.sh\n\nor\n./clean_capif_docker_services.sh -s\n</code></pre>"},{"location":"testing/robotframework/#manual-build-and-test-execution","title":"Manual Build And Test Execution","text":"<ul> <li>Build Robot docker image:</li> </ul> <pre><code>cd tools/robot\ndocker build . -t capif-robot-test:latest\n</code></pre> <ul> <li>Tests Execution:</li> </ul> <p>Execute all tests locally:</p> <pre><code>&lt;PATH_TO_REPOSITORY&gt;=path in local machine to repository cloned.\n&lt;PATH_RESULT_FOLDER&gt;=path to a folder on local machine to store results of Robot Framework execution.\n&lt;CAPIF_HOSTNAME&gt;=Is the hostname set when run.sh is executed, by default it is capifcore.\n&lt;CAPIF_HTTP_PORT&gt;=This is the port to reach when robot framework want to reach CAPIF deployment using http, this should be set to port without TLS set on Nginx, 8080 by default.\n&lt;CAPIF_HTTPS_PORT&gt;=This is the port to be used when we want to use https connection, this should be set to port with TLS set on Nginx, 443 by default\n&lt;CAPIF_REGISTER&gt;=This is the hostname of register service deployed. By default it is register.\n&lt;CAPIF_REGISTER_PORT&gt;=This is the port to be used to reach register service deployed. By default it is 8084.\n&lt;CAPIF_VAULT&gt;=This is the hostname of vault service. By default it is vault.\n&lt;CAPIF_VAULT_PORT&gt;=This is the port to be used to reach vault service. By default it is 8200.\n&lt;CAPIF_VAULT_TOKEN&gt;=Vault token to be used on request through vault. By default it is \"read-ca-token\".\n&lt;MOCK_SERVER_URL&gt;=Setup Mock server url to be used in notifications at tests marked with mockserver tag. By default it is not set.\n\nTo execute all tests run :\ndocker run -ti --rm --network=\"host\" \\\n    --add-host host.docker.internal:host-gateway \\\n    --add-host vault:host-gateway \\\n    --add-host register:host-gateway \\\n    --add-host mock-server:host-gateway \\\n    -v &lt;PATH_TO_REPOSITORY&gt;/tests:/opt/robot-tests/tests \\\n    -v &lt;PATH_RESULT_FOLDER&gt;:/opt/robot-tests/results capif-robot-test:latest  \\\n    --variable CAPIF_HOSTNAME:$CAPIF_HOSTNAME \\\n    --variable CAPIF_HTTP_PORT:$CAPIF_HTTP_PORT \\\n    --variable CAPIF_HTTPS_PORT:$CAPIF_HTTPS_PORT \\\n    --variable CAPIF_REGISTER:$CAPIF_REGISTER \\\n    --variable CAPIF_REGISTER_PORT:$CAPIF_REGISTER_PORT \\\n    --variable CAPIF_VAULT:$CAPIF_VAULT \\\n    --variable CAPIF_VAULT_PORT:$CAPIF_VAULT_PORT \\\n    --variable CAPIF_VAULT_TOKEN:$CAPIF_VAULT_TOKEN \\\n    --variable MOCK_SERVER_URL:$MOCK_SERVER_URL \\\n    --include all\n</code></pre> <p>Execute specific tests locally:</p> <pre><code>To run more specific tests, for example, only one functionality:\n&lt;TAG&gt;=Select one from list:\n  \"capif_api_acl\",\n  \"capif_api_auditing_service\",\n  \"capif_api_discover_service\",\n  \"capif_api_events\",\n  \"capif_api_invoker_management\",\n  \"capif_api_logging_service\",\n  \"capif_api_provider_management\",\n  \"capif_api_publish_service\",\n  \"capif_security_api\n\nAnd Run:\ndocker run -ti --rm --network=\"host\" \\\n    --add-host host.docker.internal:host-gateway \\\n    --add-host vault:host-gateway \\\n    --add-host register:host-gateway \\\n    --add-host mock-server:host-gateway \\\n    -v &lt;PATH_TO_REPOSITORY&gt;/tests:/opt/robot-tests/tests \\\n    -v &lt;PATH_RESULT_FOLDER&gt;:/opt/robot-tests/results capif-robot-test:latest  \\\n    --variable CAPIF_HOSTNAME:$CAPIF_HOSTNAME \\\n    --variable CAPIF_HTTP_PORT:$CAPIF_HTTP_PORT \\\n    --variable CAPIF_HTTPS_PORT:$CAPIF_HTTPS_PORT \\\n    --variable CAPIF_REGISTER:$CAPIF_REGISTER \\\n    --variable CAPIF_REGISTER_PORT:$CAPIF_REGISTER_PORT \\\n    --variable CAPIF_VAULT:$CAPIF_VAULT \\\n    --variable CAPIF_VAULT_PORT:$CAPIF_VAULT_PORT \\\n    --variable CAPIF_VAULT_TOKEN:$CAPIF_VAULT_TOKEN \\\n    --variable MOCK_SERVER_URL:$MOCK_SERVER_URL \\\n    --include &lt;TAG&gt;\n</code></pre>"},{"location":"testing/robotframework/#test-result-review","title":"Test result review","text":"<p>In order to Review results after tests, you can check general report at /report.html or if you need more detailed information /log.html, example: <ul> <li> <p>Report: </p> </li> <li> <p>Detailed information: </p> </li> </ul> <p>NOTE: If you need more detail at Robot Framework Logs you can set log level option just adding to command --loglevel DEBUG</p>"},{"location":"testing/testplan/","title":"Test Plan Index","text":"<p>List of Common API Services implemented:</p> <ul> <li>Common Operations</li> <li>Api Invoker Management</li> <li>Api Provider Management</li> <li>Api Publish Service</li> <li>Api Discover Service</li> <li>Api Events Service</li> <li>Api Security Service</li> <li>Api Logging Service</li> <li>Api Auditing Service</li> <li>Api Access Control Policy</li> </ul>"},{"location":"testing/testplan/api_access_control_policy/","title":"Test Plan for CAPIF Api Access Control Policy","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_access_control_policy/#test-case-1-retrieve-acl","title":"Test Case 1: Retrieve ACL","text":"<p>Test ID: capif_api_acl-1</p> <p>Description:</p> <p>This test case will check that an API Provider can retrieve ACL from CAPIF</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>contain only one object.</li> <li>apiInvokerId must match apiInvokerId registered previously.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-2-retrieve-acl-with-2-service-apis-published","title":"Test Case 2: Retrieve ACL with 2 Service APIs published","text":"<p>Test ID: capif_api_acl-2</p> <p>Description:</p> <p>This test case will check that an API Provider can retrieve ACL from CAPIF for 2 different serviceApis published.</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had two Service API Published on CAPIF</li> <li>API Invoker had a Security Context for both Service APIs published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1 and service_2</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information for service_1.</li> <li>Provider Get ACL information for service_2.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_2</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker for both published APIs</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL for serviceApiId1</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AEF Provider Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL for serviceApiId2</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId2}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>contain one object.</li> <li>apiInvokerId must match apiInvokerId registered previously.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-3-retrieve-acl-with-security-context-created-by-two-different-invokers","title":"Test Case 3: Retrieve ACL with security context created by two different Invokers","text":"<p>Test ID: capif_api_acl-3</p> <p>Description:</p> <p>This test case will check that an API Provider can retrieve ACL from CAPIF containing 2 objects.</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>Two API Invokers had a Security Context for same Service API published by provider.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1 and service_2</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker for both published APIs</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Repeat previous 3 steps in order to have a new Invoker.</p> </li> <li> <p>Provider Retrieve ACL for serviceApiId</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>Contain two objects.</li> <li>One object must match with apiInvokerId1 and the other one with apiInvokerId2 an registered previously.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-4-retrieve-acl-filtered-by-api-invoker-id","title":"Test Case 4: Retrieve ACL filtered by api-invoker-id","text":"<p>Test ID: capif_api_acl-4</p> <p>Description:</p> <p>This test case will check that an API Provider can retrieve ACL filtering by apiInvokerId from CAPIF containing 1 objects.</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>Two API Invokers had a Security Context for same Service API published by provider.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1 and service_2</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information with query parameter indicating first api-invoker-id.</li> <li>Provider Get ACL information with query parameter indicating second api-invoker-id.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker for both published APIs</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Repeat previous 3 steps in order to have a new Invoker.</p> </li> <li> <p>Provider Retrieve ACL for serviceApiId1</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={apiInvokerId1}</li> <li>Use serviceApiId, aefId and apiInvokerId1</li> <li>Use AEF Provider Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL for serviceApiId2</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={apiInvokerId2}</li> <li>Use serviceApiId, aefId and apiInvokerId2</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>ACL Response:</p> <ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>Contain one objects.</li> <li>Object must match with apiInvokerId1.</li> </ol> </li> </ol> </li> <li> <p>ACL Response:</p> <ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>Contain one objects.</li> <li>Object must match with apiInvokerId2.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-5-retrieve-acl-filtered-by-supported-features","title":"Test Case 5: Retrieve ACL filtered by supported-features","text":"<p>Test ID: capif_api_acl-5</p> <p>Description:</p> <p>CURRENTLY NOT SUPPORTED FEATURE</p> <p>This test case will check that an API Provider can retrieve ACL filtering by supportedFeatures from CAPIF containing 1 objects.</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>Two API Invokers had a Security Context for same Service API published by provider.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1 and service_2</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information with query parameter indicating first supported-features.</li> <li>Provider Get ACL information with query parameter indicating second supported-features.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker for both published APIs</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Repeat previous 3 steps in order to have a new Invoker.</p> </li> <li> <p>Provider Retrieve ACL for serviceApiId</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&amp;supported-features={apiInvokerId1}</li> <li>Use serviceApiId, aefId and apiInvokerId1</li> <li>Use AEF Provider Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL for serviceApiId</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&amp;supported-features={apiInvokerId2}</li> <li>Use serviceApiId, aefId and apiInvokerId2</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>ACL Response:</p> <ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>Contain one objects.</li> <li>Object must match with supportedFeatures1.</li> </ol> </li> </ol> </li> <li> <p>ACL Response:</p> <ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>Contain one objects.</li> <li>Object must match with supportedFeatures1.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-6-retrieve-acl-with-aef-id-not-valid","title":"Test Case 6: Retrieve ACL with aef-id not valid","text":"<p>Test ID: capif_api_acl-6</p> <p>Description:</p> <p>This test case will check that an API Provider can't retrieve ACL from CAPIF if aef-id is not valid</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${AEF_ID_NOT_VALID}</li> <li>Use serviceApiId and AEF_ID_NOT_VALID</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>404 Not Found Response.</li> <li>body returned must accomplish Problem Details data structure.</li> <li>apiInvokerPolicies must:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}\".</li> <li>cause with message \"Wrong id\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-7-retrieve-acl-with-service-id-not-valid","title":"Test Case 7: Retrieve ACL with service-id not valid","text":"<p>Test ID: capif_api_acl-7</p> <p>Description:</p> <p>This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id is not valid</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${aef_id}</li> <li>Use NOT_VALID_SERVICE_API_ID and aef_id</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>404 Not Found Response.</li> <li>body returned must accomplish Problem Details data structure.</li> <li>apiInvokerPolicies must:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}\".</li> <li>cause with message \"Wrong id\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-8-retrieve-acl-with-service-api-id-and-aef-id-not-valid","title":"Test Case 8: Retrieve ACL with service-api-id and aef-id not valid","text":"<p>Test ID: capif_api_acl-8</p> <p>Description:</p> <p>This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id and aef-id are not valid</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${AEF_ID_NOT_VALID}</li> <li>Use NOT_VALID_SERVICE_API_ID and aef_id</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>404 Not Found Response.</li> <li>body returned must accomplish Problem Details data structure.</li> <li>apiInvokerPolicies must:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}\".</li> <li>cause with message \"Wrong id\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-9-retrieve-acl-without-securitycontext-created-previously-by-invoker","title":"Test Case 9: Retrieve ACL without SecurityContext created previously by Invoker","text":"<p>Test ID: capif_api_acl-9</p> <p>Description:</p> <p>This test case will check that an API Provider can't retrieve ACL if no invoker had requested Security Context to CAPIF</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker created but no Security Context for Service API published had been requested.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li> <p>Discover published APIs</p> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>404 Not Found Response.</li> <li>body returned must accomplish Problem Details data structure.</li> <li>apiInvokerPolicies must:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}\".</li> <li>cause with message \"Wrong id\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-10-retrieve-acl-filtered-by-api-invoker-id-not-present","title":"Test Case 10: Retrieve ACL filtered by api-invoker-id not present","text":"<p>Test ID: capif_api_acl-10</p> <p>Description:</p> <p>This test case will check that an API Provider get not found response if filter by not valid api-invoker-id doesn't match any registered ACL.</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={NOT_VALID_API_INVOKER_ID}</li> <li>Use serviceApiId, aefId and NOT_VALID_API_INVOKER_ID</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>ACL Response:<ol> <li>404 Not Found Response.</li> <li>body returned must accomplish Problem Details data structure.</li> <li>apiInvokerPolicies must:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}\".</li> <li>cause with message \"Wrong id\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-11-retrieve-acl-with-apf-certificate","title":"Test Case 11: Retrieve ACL with APF Certificate","text":"<p>Test ID: capif_api_acl-11</p> <p>Description:</p> <p>This test case will check that an API Provider can't retrieve ACL from CAPIF using APF Certificate</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use APF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"Certificate not authorized\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-12-retrieve-acl-with-amf-certificate","title":"Test Case 12: Retrieve ACL with AMF Certificate","text":"<p>Test ID: capif_api_acl-12</p> <p>Description:</p> <p>This test case will check that an API Provider can't retrieve ACL from CAPIF using AMF Certificate</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AMF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"Certificate not authorized\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-13-retrieve-acl-with-invoker-certificate","title":"Test Case 13: Retrieve ACL with Invoker Certificate","text":"<p>Test ID: capif_api_acl-13</p> <p>Description:</p> <p>This test case will check that an API Provider can't retrieve ACL from CAPIF using Invoker Certificate</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"Certificate not authorized\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_access_control_policy/#test-case-14-no-acl-for-invoker-after-be-removed","title":"Test Case 14: No ACL for invoker after be removed","text":"<p>Test ID: capif_api_acl-14</p> <p>Description:</p> <p>This test case will check that ACLs are removed after invoker is removed.</p> <p>Pre-Conditions:</p> <ul> <li>API Provider had a Service API Published on CAPIF</li> <li>API Invoker had a Security Context for Service API published and ACL is present</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Provider at CCF.</li> <li>Publish a provider API with name service_1</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Provider Get ACL information of invoker.</li> <li>Remove Invoker from CAPIF.</li> <li>Provider Get ACL information of invoker.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform Invoker Onboarding store apiInvokerId</p> </li> <li>Discover published APIs</li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Provider Retrieve ACL</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={api-invoker-id}</li> <li>Use serviceApiId, aefId and api-invoker-id</li> <li>Use AEF Provider Certificate</li> </ul> </li> <li>Remove Invoker from CAPIF</li> <li>Provider Retrieve ACL<ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={api-invoker-id}</li> <li>Use serviceApiId, aefId and api-invoker-id</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:   1. ACL Response:      1. 200 OK Response.      2. body returned must accomplish AccessControlPolicyList data structure.      3. apiInvokerPolicies must:         1. contain only one object.         2. apiInvokerId must match apiInvokerId registered previously.</p> <ol> <li>ACL Response:<ol> <li>404 Not Found Response.</li> <li>body returned must accomplish Problem Details data structure.</li> <li>apiInvokerPolicies must:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: None and supportedFeatures: None\".</li> <li>cause with message \"Wrong id\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_auditing_service/","title":"Test Plan for CAPIF Api Auditing Service","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_auditing_service/#test-case-1-get-capif-log-entry","title":"Test Case 1: Get CAPIF Log Entry.","text":"<p>Test ID: capif_api_auditing-1</p> <p>Description:</p> <p>This test case will check that a CAPIF AMF can get log entry to Logging Service</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> <li>Log Entry exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry   4. Get Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding, invoker onboarding </p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Create Log Entry:</p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body log entry request body</li> <li>Use AEF Certificate</li> </ul> </li> <li> <p>Get Log:</p> <ol> <li>Send GET to https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}</li> <li>Use AMF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>200 OK</li> <li>Response Body must follow InvocationLog data structure with:<ul> <li>aefId</li> <li>apiInvokerId</li> <li>logs</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_auditing_service/#test-case-2-get-capif-log-entry-with-no-log-entry-in-capif","title":"Test Case 2: Get CAPIF Log Entry With no Log entry in CAPIF.","text":"<p>Test ID: capif_api_auditing-2</p> <p>Description:</p> <p>This test case will check that a CAPIF AEF can create log entry to Logging Service</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Get Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding, invoker onboarding </p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Get Log:</p> <ol> <li>Send GET to https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}</li> <li>Use AMF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found Log Entry in CAPIF\".</li> <li>cause with message \"Not Exist Logs with the filters applied\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_auditing_service/#test-case-3-get-capif-log-entry-without-aef-id-and-api-invoker-id","title":"Test Case 3: Get CAPIF Log Entry without aef-id and api-invoker-id.","text":"<p>Test ID: capif_api_auditing-3</p> <p>Description:</p> <p>This test case will check that a CAPIF AEF can create log entry to Logging Service</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is no pre-authorised (has no valid AMF cert from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> <li>Log Entry exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry   4. Get Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding, invoker onboarding </p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Create Log Entry:</p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body log entry request body</li> <li>Use AEF Certificate</li> </ul> </li> <li> <p>Get Log:</p> <ol> <li>Send GET to https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs</li> <li>Use AMF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>400 Bad Request</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 400</li> <li>title with message \"Bad Request\"</li> <li>detail with message \"aef_id and api_invoker_id parameters are mandatory\".</li> <li>cause with message \"Mandatory parameters missing\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_auditing_service/#test-case-4-get-capif-log-entry-with-filtter-api-version","title":"Test Case 4: Get CAPIF Log Entry with filtter api-version.","text":"<p>Test ID: capif_api_auditing-4</p> <p>Description:</p> <p>This test case will check that a CAPIF AMF can get log entry to Logging Service</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> <li>Log Entry exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry   4. Get Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding, invoker onboarding </p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Create Log Entry:</p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body log entry request body</li> <li>Use AEF Certificate</li> </ul> </li> <li> <p>Get Log:</p> <ol> <li>Send GET to https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}&amp;api-version={v1}</li> <li>Use AMF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>200 OK</li> <li>Response Body must follow InvocationLog data structure with:<ul> <li>aefId</li> <li>apiInvokerId</li> <li>logs</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_auditing_service/#test-case-5-get-capif-log-entry-with-filter-api-version-but-not-exist-in-log-entry","title":"Test Case 5: Get CAPIF Log Entry with filter api-version but not exist in log entry.","text":"<p>Test ID: capif_api_auditing-4</p> <p>Description:</p> <p>This test case will check that a CAPIF AMF can get log entry to Logging Service</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> <li>Log Entry exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry   4. Get Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding, invoker onboarding </p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Create Log Entry:</p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body log entry request body</li> <li>Use AEF Certificate</li> </ul> </li> <li> <p>Get Log:</p> <ol> <li>Send GET to https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}&amp;api-version={v58}</li> <li>Use AMF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>detail with message \"Parameters do not match any log entry\"</li> <li>cause with message \"No logs found\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_discover_service/","title":"Test Plan for CAPIF Discover Service","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_discover_service/#test-case-1-discover-published-service-apis-by-authorised-api-invoker","title":"Test Case 1: Discover Published service APIs by Authorised API Invoker","text":"<p>Test ID: capif_api_discover_service-1</p> <p>Description:</p> <p>This test case will check if Network App (Invoker) can discover published service APIs.</p> <p>Pre-Conditions:</p> <ul> <li>Service APIs are published.</li> <li>Network App was registered previously</li> <li>Network App was onboarded previously with {onboardingId}</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration and Invoker Onboarding</li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li>Request Discover Published APIs:<ul> <li>Send GET to https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Use Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li>Response to Discover Request By Invoker:<ol> <li>200 OK response.</li> <li>Response body must follow DiscoveredAPIs data structure:<ul> <li>Check if DiscoveredAPIs contains the API Published previously</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_discover_service/#test-case-2-discover-published-service-apis-by-non-authorised-api-invoker","title":"Test Case 2: Discover Published service APIs by Non Authorised API Invoker","text":"<p>Test ID: capif_api_discover_service-2</p> <p>Description:</p> <p>This test case will check that an API Publisher can't discover published APIs because is not authorized.</p> <p>Pre-Conditions:</p> <ul> <li>Service APIs are published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover Service APIs by no invoker entity</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration and Invoker Onboarding</li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li>Request Discover Published APIs by no invoker entity:<ul> <li>Send GET to https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Use not Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Discover Request By no invoker entity:</p> <ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"User not authorized\".</li> <li>cause with message \"Certificate not authorized\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_discover_service/#test-case-3-discover-published-service-apis-by-not-registered-api-invoker","title":"Test Case 3: Discover Published service APIs by not registered API Invoker","text":"<p>Test ID: capif_api_discover_service-3</p> <p>Description:</p> <p>This test case will check that a not registered invoker is forbidden to discover published APIs.</p> <p>Pre-Conditions:</p> <ul> <li>Service APIs are published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover Service APIs by Publisher</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration and Invoker Onboarding</li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li>Request Discover Published APIs with not valid apiInvoker:<ul> <li>Send GET to https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={INVOKER_NOT_REGISTERED}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Discover Request By Invoker:</p> <ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"API Invoker does not exist\".</li> <li>cause with message \"API Invoker id not found\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_discover_service/#test-case-4-discover-published-service-apis-by-registered-api-invoker-with-1-result-filtered","title":"Test Case 4: Discover Published service APIs by registered API Invoker with 1 result filtered","text":"<p>Test ID: capif_api_discover_service-4</p> <p>Description:</p> <p>This test case will check if Network App (Invoker) can discover published service APIs.</p> <p>Pre-Conditions:</p> <ul> <li>At least 2 Service APIs are published.</li> <li>Network App was registered previously</li> <li>Network App was onboarded previously with {onboardingId}</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Discover filtered by api-name service_1 Service APIs by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration and Invoker Onboarding</li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_2</li> <li>Use APF Certificate</li> </ul> </li> <li>Request Discover Published APIs filtering by api-name:<ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&amp;api-name=service_1**</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> <li>filter by api-name service_1</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Publish request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li>Response to Discover Request By Invoker:<ol> <li>200 OK response.</li> <li>Response body must follow DiscoveredAPIs data structure:<ul> <li>Check if DiscoveredAPIs contains previously registered Service APIs published.</li> </ul> </li> </ol> </li> <li>Response to Discover Request By Invoker:<ol> <li>200 OK response.</li> <li>Response body must follow DiscoveredAPIs data structure:<ul> <li>Check if DiscoveredAPIs contains only Service API published with api-name service_1</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_discover_service/#test-case-5-discover-published-service-apis-by-registered-api-invoker-filtered-with-no-match","title":"Test Case 5: Discover Published service APIs by registered API Invoker filtered with no match","text":"<p>Test ID: capif_api_discover_service-5</p> <p>Description:</p> <p>This test case will check if Network App (Invoker) can discover published service APIs.</p> <p>Pre-Conditions:</p> <ul> <li>At least 2 Service APIs are published.</li> <li>Network App was registered previously</li> <li>Network App was onboarded previously with {onboardingId}</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Discover filtered by api-name not published Service APIs by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration and Invoker Onboarding</li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_2</li> <li>Use APF Certificate</li> </ul> </li> <li>Request Discover Published APIs filtering by api-name not published:<ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&amp;api-name=NOT_VALID_NAME</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> <li>filter by api-name NOT_VALID_NAME</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Publish request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li>Response to Discover Request By Invoker:<ol> <li>200 OK response.</li> <li>Response body must follow DiscoveredAPIs data structure:<ul> <li>Check if DiscoveredAPIs contains previously registered Service APIs published.</li> </ul> </li> </ol> </li> <li>Response to Discover Request By Invoker:<ol> <li>404 Not Found response.</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"API Invoker {api_invoker_id} has no API Published that accomplish filter conditions\".</li> <li>cause with message \"No API Published accomplish filter conditions\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_discover_service/#test-case-6-discover-published-service-apis-by-registered-api-invoker-not-filtered","title":"Test Case 6: Discover Published service APIs by registered API Invoker not filtered","text":"<p>Test ID: capif_api_discover_service-6</p> <p>Description:</p> <p>This test case will check if Network App (Invoker) can discover published service APIs.</p> <p>Pre-Conditions:</p> <ul> <li>2 Service APIs are published.</li> <li>Network App was registered previously</li> <li>Network App was onboarded previously with {onboardingId}</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Discover without filter by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration and Invoker Onboarding</li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_2</li> <li>Use APF Certificate</li> </ul> </li> <li>Request Discover Published APIs not filtered:<ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Discover Request By Invoker:</p> <ol> <li>200 OK response.</li> <li>Response body must follow DiscoveredAPIs data structure:<ul> <li>Check if DiscoveredAPIs contains the 2 previously registered Service APIs published.</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/","title":"Test Plan for CAPIF Api Events Service","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_events_service/#test-case-1-creates-a-new-individual-capif-event-subscription","title":"Test Case 1: Creates a new individual CAPIF Event Subscription.","text":"<p>Test ID: capif_api_events-1</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (Invoker or Publisher) can Subscribe to Events</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Subscribe to Events</li> <li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Event Subscription:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body</li> <li>Use Invoker Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Event Subscription must accomplish:</p> <ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li> <p>Event Subscriptions are stored in CAPIF Database</p> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-2-creates-a-new-individual-capif-event-subscription-with-invalid-subscriberid","title":"Test Case 2: Creates a new individual CAPIF Event Subscription with Invalid SubscriberId","text":"<p>Test ID: capif_api_events-2</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Subscribe to Events without valid SubcriberId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is not pre-authorised (has invalid InvokerId or apfId)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Subscribe to Events</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Event Subscription:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_NOT_REGISTERED}/subscriptions</li> <li>body event subscription request body</li> <li>Use Invoker Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Event Subscription must accomplish:</p> <ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker or APF or AEF or AMF Not found\".</li> <li>cause with message \"Subscriber Not Found\".</li> </ul> </li> </ol> </li> <li> <p>Event Subscriptions are not stored in CAPIF Database</p> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-3-deletes-an-individual-capif-event-subscription","title":"Test Case 3: Deletes an individual CAPIF Event Subscription","text":"<p>Test ID: capif_api_events-3</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (Invoker or Publisher) can Delete an Event Subscription</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Subscribe to Events</li> <li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li> <li>Remove Event Subscription</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Event Subscription:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body</li> <li>Use Invoker Certificate</li> </ol> </li> <li> <p>Remove Event Subscription:</p> <ol> <li>Send DELETE to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>Use Invoker Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Event Subscription must accomplish:</p> <ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li> <p>Event Subscriptions are stored in CAPIF Database</p> </li> <li> <p>Remove Event Subscription:</p> <ol> <li>204 No Content</li> </ol> </li> <li> <p>Event Subscription is not present at CAPIF Database.</p> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-4-deletes-an-individual-capif-event-subscription-with-invalid-subscriberid","title":"Test Case 4: Deletes an individual CAPIF Event Subscription with invalid SubscriberId","text":"<p>Test ID: capif_api_events-4</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete to Events without valid SubcriberId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId).</li> <li>CAPIF subscriber is subscribed to Events.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Subscribe to Events</li> <li>Retrieve Location Header with subscriptionId.</li> <li>Remove Event Subscribed with not valid Subscriber.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Event Subscription:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body</li> <li>Use Invoker Certificate</li> </ol> </li> <li> <p>Remove Event Subcription with not valid subscriber:</p> <ol> <li>Send DELETE to https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_ID_NOT_VALID}/subscriptions/{subcriptionId}</li> <li>Use Invoker Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Event Subscription must accomplish:</p> <ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li> <p>Event Subscriptions are stored in CAPIF Database</p> </li> <li> <p>Error Response Body must accomplish with ProblemDetails data structure with:</p> <ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker or APF or AEF or AMF Not found\".</li> <li>cause with message \"Subscriber Not Found\".</li> </ul> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-5-deletes-an-individual-capif-event-subscription-with-invalid-subscriptionid","title":"Test Case 5: Deletes an individual CAPIF Event Subscription with invalid SubscriptionId","text":"<p>Test ID: capif_api_events-5</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete an Event Subscription without valid SubscriptionId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has invalid InvokerId or apfId).</li> <li>CAPIF subscriber is subscribed to Events.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Subscribe to Events</li> <li>Retrieve Location Header with subscriptionId.</li> <li>Remove Event Subscribed with not valid Subscriber.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Event Subscription:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body</li> <li>Use Invoker Certificate</li> </ol> </li> <li> <p>Remove Event Subcription with not valid subscriber:</p> <ol> <li>Send DELETE to to https://{CAPIF_HOSTNAME}/capif-events/v1/{subcriberId}/subscriptions/{SUBSCRIPTION_ID_NOT_VALID}</li> <li>Use Invoker Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li> <p>Response to Event Subscription must accomplish:</p> <ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li> <p>Event Subscriptions are stored in CAPIF Database</p> </li> <li>Remove Event Subscription with not valid subscriber:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>detail with message \"Service API not existing\".</li> <li>cause with message \"Event API subscription id not found\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-6-invoker-receives-service-api-invocation-events","title":"Test Case 6: Invoker receives Service API Invocation events","text":"<p>Test ID: capif_api_events-6, mockserver</p> <p>Description:</p> <p>This test case will check that a CAPIF Invoker subscribed to SERVICE_API_INVOCATION_SUCCESS and SERVICE_API_INVOCATION_FAILURE, receive the notification when AEF Send TO logging service result of invocations to their APIs.</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> <li>CAPIF provider is correctly registered and published APIs.</li> <li>API Provider had a Service API Published on CAPIF</li> <li>Mock Server is up and running to receive requests.</li> <li>Mock Server is clean.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register provider and publish one API at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover published APIs and extract apiIds and apiNames</li> <li>Subscribe to SERVICE_API_INVOCATION_SUCCESS and SERVICE_API_INVOCATION_FAILURE event filtering by aefId.</li> <li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li> <li>Emulate Success and Failure on API invocation of provider by Invoker, using Invocation Logs API.</li> </ol> <p>Information of Test:</p> <ol> <li>Perform provider registration</li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform invoker onboarding</p> </li> <li> <p>Discover published APIs:</p> <ul> <li>Get Api Ids And Api Names from response.</li> </ul> </li> <li> <p>Event Subscription to SERVICE_API_INVOCATION_SUCCESS and SERVICE_API_INVOCATION_FAILURE of provider previously registered:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body with:<ol> <li>events: ['SERVICE_API_INVOCATION_SUCCESS','SERVICE_API_INVOCATION_FAILURE']</li> <li>eventFilter: only receive events from provider's aefId.</li> </ol> </li> <li>Use Invoker Certificate</li> </ol> </li> <li> <p>Create Log Entry emulating provider receive Success and Failure api invocation from invoker:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body log entry request body with:<ol> <li>aefId from provider published.</li> <li>apiInvokerId from invoker onboarded.</li> <li>apiId of published API</li> <li>apiName of published API</li> <li>200 and 400 results in two logs.</li> </ol> </li> <li>Use AEF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Event Subscription must accomplish:<ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li>Response to creation of log entry on CCF must accomplish:<ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/api-invocation-logs/{apiVersion}/{aefId}/subscriptions/{logId}</li> </ol> </li> <li>Mock Server received messages must accomplish:<ol> <li>Two Events have been received.</li> <li>Validate received events follow EventNotification data structure, with invocationLog in eventDetail parameter.<ol> <li>One should be SERVICE_API_INVOCATION_SUCCESS related with 200 result at Log.</li> <li>The other one must be SERVICE_API_INVOCATION_FAILURE related with 400 result at Log.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-7-invoker-subscribe-to-service-api-available-and-unavailable-events","title":"Test Case 7: Invoker subscribe to Service API Available and Unavailable events","text":"<p>Test ID: capif_api_events-7, mockserver</p> <p>Description:</p> <p>This test case will check that a CAPIF Invoker subscribed to SERVICE_API_AVAILABLE and SERVICE_API_UNAVAILABLE, receive the notification when AEF publish and remove it. </p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> <li>CAPIF provider is correctly registered and published APIs.</li> <li>Mock Server is up and running to receive requests.</li> <li>Mock Server is clean.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register provider and publish one API at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover published APIs and extract apiIds and apiNames</li> <li>Subscribe to SERVICE_API_AVAILABLE and SERVICE_API_UNAVAILABLE event filtering by aefId.</li> <li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li> <li>Provider publish new API.</li> <li>Provider remove published API.</li> </ol> <p>Information of Test:</p> <ol> <li>Perform provider registration</li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Perform invoker onboarding</p> </li> <li> <p>Discover published APIs:</p> <ul> <li>Get Api Ids And Api Names from response.</li> </ul> </li> <li> <p>Event Subscription to SERVICE_API_AVAILABLE and SERVICE_API_UNAVAILABLE of provider previously registered:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body with:<ol> <li>events: ['SERVICE_API_AVAILABLE','SERVICE_API_UNAVAILABLE']</li> <li>eventFilter: only receive events from provider's aefId.</li> </ol> </li> <li>Use Invoker Certificate</li> </ol> </li> <li> <p>Publish new Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_2</li> <li>Store serviceApiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Remove published Service API at CCF:</p> <ul> <li>Send DELETE to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID}</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Event Subscription must accomplish:</p> <ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li> <p>Mock Server received messages must accomplish:</p> <ol> <li>Two Events have been received.</li> <li>Validate received events follow EventNotification data structure, with apiIds in eventDetail parameter.<ol> <li>One should be SERVICE_API_AVAILABLE apiId of service_2 published API.</li> <li>The other one must be SERVICE_API_UNAVAILABLE apiId of service_1 published API.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-8-invoker-subscribe-to-service-api-update","title":"Test Case 8: Invoker subscribe to Service API Update","text":"<p>Test ID: capif_api_events-8, mockserver</p> <p>Description:</p> <p>This test case will check that a CAPIF Invoker subscribed to SERVICE_API_UPDATE, receive the notification when AEF Update some information on API Published.</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> <li>CAPIF provider is correctly registered and published APIs.</li> <li>API Provider had a Service API Published on CAPIF</li> <li>Mock Server is up and running to receive requests.</li> <li>Mock Server is clean.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider and publish one API at CCF</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Discover published APIs and extract apiIds and apiNames</li> <li>Subscribe to SERVICE_API_UPDATE event filtering by aefId.</li> <li>Retrieve {subscriberId} and {subscriptionId} from Location Header at event subscription</li> <li>Provider update information of Service API Published.</li> </ol> <p>Information of Test:</p> <ol> <li>Check and Clean Mock Server</li> <li>Perform provider registration</li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> <li>Store serviceApiId</li> </ul> </li> <li> <p>Perform invoker onboarding</p> </li> <li> <p>Discover published APIs:</p> <ul> <li>Get Api Ids And Api Names from response.</li> </ul> </li> <li> <p>Event Subscription to SERVICE_API_UPDATE of provider previously registered:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body with:<ol> <li>events: ['SERVICE_API_UPDATE']</li> <li>eventFilter: only receive events from provider's aefId.</li> </ol> </li> <li>Use Invoker Certificate</li> </ol> </li> <li> <p>Update published API at CCF:</p> <ul> <li>Send PUT to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</li> <li>body [service api description] with overrided apiName to service_1_modified**</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Event Subscription must accomplish:<ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li>Response to Update Published Service API:<ol> <li>200 OK</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiName service_1_modified**</li> </ul> </li> </ol> </li> <li>Mock Server received messages must accomplish:<ol> <li>One Event has been received.</li> <li>Validate received events follow EventNotification data structure, with serviceAPIDescriptions in eventDetail parameter.<ol> <li>Event should be SERVICE_API_UPDATE with eventDetail with modified apiName.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-9-provider-subscribe-to-api-invoker-events","title":"Test Case 9: Provider subscribe to API Invoker events","text":"<p>Test ID: capif_api_events-9, mockserver</p> <p>Description:</p> <p>This test case will check that a CAPIF Provider subscribed to API Invoker events (API_INVOKER_ONBOARDED, API_INVOKER_UPDATED and API_INVOKER_OFFBOARDED), receive the notifications when Invoker is onboarded, updated and removed respectively.</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> <li>CAPIF provider is correctly registered.</li> <li>Mock Server is up and running to receive requests.</li> <li>Mock Server is clean.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Subscribe Provider to API_INVOKER_ONBOARDED, API_INVOKER_UPDATED and API_INVOKER_OFFBOARDED events.</li> <li>Register Invoker and Onboard Invoker at CCF</li> <li>Update Onboarding Information at CCF with a minor change on \"notificationDestination\"</li> <li>Offboard Invoker</li> </ol> <p>Information of Test:</p> <ol> <li>Check and Clean Mock Server</li> <li>Perform provider registration</li> <li>Event Subscription to API_INVOKER_ONBOARDED, API_INVOKER_UPDATED and API_INVOKER_OFFBOARDED events:<ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body with:<ol> <li>events: ['API_INVOKER_ONBOARDED', 'API_INVOKER_UPDATED', 'API_INVOKER_OFFBOARDED']</li> </ol> </li> <li>Use Provider AMF Certificate</li> </ol> </li> <li>Perform invoker onboarding</li> <li>Update information of previously onboarded Invoker:<ul> <li>Send PUT to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</li> <li>Reference Request Body is: [put invoker onboarding body]</li> <li>\"notificationDestination\": \"http://host.docker.internal:8086/netapp_new_callback\",</li> </ul> </li> <li>Offboard:<ul> <li>Send DELETE to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Event Subscription must accomplish:<ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li>Response to Update Request (PUT) with minor change must contain:<ol> <li>200 OK response.</li> <li>notificationDestination on response must contain the new value</li> </ol> </li> <li>Response to Offboard Request (DELETE) must contain:<ol> <li>204 No Content</li> </ol> </li> <li>Mock Server received messages must accomplish:<ol> <li>Three Events have been received.</li> <li>Validate received events follow EventNotification data structure, with apiInvokerIds in eventDetail parameter.<ol> <li>One Event should be API_INVOKER_ONBOARDED with eventDetail with modified apiInvokerId.</li> <li>One Event should be API_INVOKER_UPDATED with eventDetail with modified apiInvokerId.</li> <li>One Event should be API_INVOKER_OFFBOARDED with eventDetail with modified apiInvokerId.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-10-provider-subscribed-to-acl-update-event","title":"Test Case 10: Provider subscribed to ACL update event","text":"<p>Test ID: capif_api_events-10, mockserver</p> <p>Description:</p> <p>This test case will check that a CAPIF Provider subscribed to ACCESS_CONTROL_POLICY_UPDATE receive a notification when ACL Changes.</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> <li>CAPIF provider is correctly registered.</li> <li>API Provider had one Service API Published on CAPIF</li> <li>API Invoker had a Security Context for the Service API published by provider.</li> <li>Mock Server is up and running to receive requests.</li> <li>Mock Server is clean.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF.</li> <li>Publish a provider API with name service_1.</li> <li>Register Invoker and Onboard Invoker at CCF.</li> <li>Subscribe Provider to ACCESS_CONTROL_POLICY_UPDATE event.</li> <li>Discover APIs filtered by aef_id</li> <li>Create Security Context for Invoker.</li> <li>Provider Retrieve ACL</li> </ol> <p>Information of Test:</p> <ol> <li>Check and Clean Mock Server</li> <li>Perform provider registration</li> <li>Perform invoker onboarding</li> <li>Event Subscription to ACCESS_CONTROL_POLICY_UPDATE event:<ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body with:<ol> <li>events: ['ACCESS_CONTROL_POLICY_UPDATE']</li> <li>eventFilters: apiInvokerIds array with apiInvokerId of invoker</li> </ol> </li> <li>Use Provider AMF Certificate</li> </ol> </li> <li>Discover published APIs</li> <li>Create Security Context for Invoker<ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li>Provider Retrieve ACL<ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AEF Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Event Subscription must accomplish:<ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li>Create security context:<ol> <li>201 Created response.</li> <li>body returned must accomplish ServiceSecurity data structure.</li> <li>Location Header must contain the new resource URL {apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</li> </ol> </li> <li>ACL Response:<ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>contain only one object.</li> <li>apiInvokerId must match apiInvokerId registered previously.</li> </ol> </li> </ol> </li> <li>Mock Server received messages must accomplish:<ol> <li>One Event has been received.</li> <li>Validate received event follow EventNotification data structure, with accCtrlPolListExt in eventDetail parameter.<ol> <li>One Event should be ACCESS_CONTROL_POLICY_UPDATE with eventDetail with accCtrlPolListExt including the apiId and apiInvokerPolicies.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-11-provider-receives-an-acl-unavailable-event-when-invoker-remove-security-context","title":"Test Case 11: Provider receives an ACL unavailable event when invoker remove Security Context.","text":"<p>Test ID: capif_api_events-11, mockserver</p> <p>Description:</p> <p>This test case will check that a CAPIF Invoker subscribed to ACCESS_CONTROL_POLICY_UNAVAILABLE will receive the notification when AEF remove Security Context created previously.</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> <li>CAPIF provider is correctly registered.</li> <li>API Provider had one Service API Published on CAPIF</li> <li>Mock Server is up and running to receive requests.</li> <li>Mock Server is clean.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF.</li> <li>Publish a provider API with name service_1.</li> <li>Register Invoker and Onboard Invoker at CCF.</li> <li>Subscribe Invoker to ACCESS_CONTROL_POLICY_UNAVAILABLE event.</li> <li>Discover APIs filtered by aef_id</li> <li>Create Security Context for Invoker.</li> <li>Provider Retrieve ACL.</li> <li>Remove Security Context for Invoker.</li> </ol> <p>Information of Test:</p> <ol> <li>Check and Clean Mock Server</li> <li>Perform provider registration</li> <li>Perform invoker onboarding</li> <li>Event Subscription to ACCESS_CONTROL_POLICY_UNAVAILABLE event:<ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body with:<ol> <li>events: ['ACCESS_CONTROL_POLICY_UNAVAILABLE']</li> <li>eventFilters: apiInvokerIds array with apiInvokerId of invoker</li> </ol> </li> <li>Use Invoker Certificate</li> </ol> </li> <li>Discover published APIs</li> <li>Create Security Context for Invoker<ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li>Provider Retrieve ACL<ul> <li>Send GET https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</li> <li>Use serviceApiId and aefId</li> <li>Use AEF Provider Certificate</li> </ul> </li> <li>Delete Security Context of Invoker by Provider:<ul> <li>Send DELETE https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Use AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Event Subscription must accomplish:<ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li>Create security context:<ol> <li>201 Created response.</li> <li>body returned must accomplish ServiceSecurity data structure.</li> <li>Location Header must contain the new resource URL {apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</li> </ol> </li> <li>ACL Response:<ol> <li>200 OK Response.</li> <li>body returned must accomplish AccessControlPolicyList data structure.</li> <li>apiInvokerPolicies must:<ol> <li>contain only one object.</li> <li>apiInvokerId must match apiInvokerId registered previously.</li> </ol> </li> </ol> </li> <li>Delete security context:<ol> <li>204 No Content response.</li> </ol> </li> <li>Mock Server received messages must accomplish:<ol> <li>One Event has been received.</li> <li>Validate received event follow EventNotification data structure, without eventDetail parameter.<ol> <li>One Event should be ACCESS_CONTROL_POLICY_UNAVAILABLE without eventDetail.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_events_service/#test-case-12-invoker-receives-an-invoker-authorization-revoked-and-acl-unavailable-event-when-provider-revoke-invoker-authorization","title":"Test Case 12: Invoker receives an Invoker Authorization Revoked and ACL unavailable event when Provider revoke Invoker Authorization.","text":"<p>Test ID: capif_api_events-12, mockserver</p> <p>Description:</p> <p>This test case will check that a CAPIF Invoker subscribed to API_INVOKER_AUTHORIZATION_REVOKED and ACCESS_CONTROL_POLICY_UNAVAILABLE receive both notification when AEF revoke invoker's authorization.</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li> <li>CAPIF provider is correctly registered.</li> <li>API Provider had one Service API Published on CAPIF</li> <li>Mock Server is up and running to receive requests.</li> <li>Mock Server is clean.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF.</li> <li>Publish a provider API with name service_1.</li> <li>Register Invoker and Onboard Invoker at CCF.</li> <li>Subscribe Invoker to ACCESS_CONTROL_POLICY_UNAVAILABLE and API_INVOKER_AUTHORIZATION_REVOKED events.</li> <li>Discover APIs filtered by aef_id</li> <li>Create Security Context for Invoker.</li> <li>Revoke Authorization by Provider.</li> </ol> <p>Information of Test:</p> <ol> <li>Check and Clean Mock Server</li> <li>Perform provider registration</li> <li>Perform invoker onboarding</li> <li>Event Subscription to ACCESS_CONTROL_POLICY_UNAVAILABLE and API_INVOKER_AUTHORIZATION_REVOKED event:<ol> <li>Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</li> <li>body event subscription request body with:<ol> <li>events: ['ACCESS_CONTROL_POLICY_UNAVAILABLE','API_INVOKER_AUTHORIZATION_REVOKED']</li> <li>eventFilters: apiInvokerIds array with apiInvokerId of invoker</li> </ol> </li> <li>Use Invoker Certificate</li> </ol> </li> <li>Discover published APIs</li> <li>Create Security Context for Invoker<ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> <li>Revoke Authorization by Provider:<ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete</li> <li>body security notification body</li> <li>Using AEF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Event Subscription must accomplish:<ol> <li>201 Created</li> <li>The URI of the created resource shall be returned in the \"Location\" HTTP header, following this structure: {apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</li> <li>Response Body must follow EventSubscription data structure.</li> </ol> </li> <li>Create security context:<ol> <li>201 Created response.</li> <li>body returned must accomplish ServiceSecurity data structure.</li> <li>Location Header must contain the new resource URL {apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</li> </ol> </li> <li>Revoke Authorization:<ol> <li>204 No Content response.</li> </ol> </li> <li>Mock Server received messages must accomplish:<ol> <li>Two Events has been received.</li> <li>Validate received event follow EventNotification data structure, without eventDetail parameter.<ol> <li>One Event should be ACCESS_CONTROL_POLICY_UNAVAILABLE without eventDetail.</li> <li>One Event should be API_INVOKER_AUTHORIZATION_REVOKED without eventDetail.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_invoker_management/","title":"Test Plan for CAPIF Api Invoker Management","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_invoker_management/#test-case-1-onboard-network-app","title":"Test Case 1: Onboard Network App","text":"<p>Test ID: capif_api_invoker_management-1</p> <p>Description:</p> <p>This test will try to register new Network App at CAPIF Core.</p> <p>Pre-Conditions:</p> <ul> <li>Network App was not registered previously</li> <li>Network App was not onboarded previously</li> <li>Preconditions: The administrator must have previously registered the User.</li> </ul> <p>Execution Steps:</p> <ol> <li>Retrieve access_token by User from register</li> <li>Onboard Invoker at CCF</li> <li>Store signed Certificate</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at invoker</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Onboard Invoker:</p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers</li> <li>Reference Request Body: invoker onboarding body</li> <li>\"onboardingInformation\"-&gt;\"apiInvokerPublicKey\": must contain public key generated by Invoker.</li> <li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_invoker_management/#test-case-2-onboard-network-app-already-onboarded","title":"Test Case 2: Onboard Network App Already onboarded","text":"<p>Test ID: capif_api_invoker_management-2</p> <p>Description:</p> <p>This test will check second onboard of same Network App is not allowed.</p> <p>Pre-Conditions:</p> <ul> <li>Network App was registered previously</li> <li>Network App was onboarded previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Network App at CCF</li> <li>Onboard Network App at CCF</li> <li>Store signed Certificate at Network App</li> <li>Onboard Again the Network App at CCF</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Repeat Onboard Invoker:</p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers</li> <li>Reference Request Body: invoker onboarding body</li> <li>\"onboardingInformation\"-&gt;\"apiInvokerPublicKey\": must contain public key generated by Invoker.</li> <li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li>Response to Second Onboard of Network App must accomplish:<ol> <li>403 Forbidden</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 403</li> <li>title with message \"Forbidden\"</li> <li>detail with message \"Invoker Already registered\".</li> <li>cause with message \"Identical invoker public key\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_invoker_management/#test-case-3-update-onboarded-network-app","title":"Test Case 3: Update Onboarded Network App","text":"<p>Test ID: capif_api_invoker_management-3</p> <p>Description:</p> <p>This test will try to update information of previous onboard Network App at CAPIF Core.</p> <p>Pre-Conditions:</p> <ul> <li>Network App was registered previously</li> <li>Network App was onboarded previously with {onboardingId}</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker at CCF</li> <li>Onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Update Onboarding Information at CCF with a minor change on \"notificationDestination\"</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Update information of previously onboarded Invoker:</p> <ul> <li>Send PUT to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</li> <li>Reference Request Body is: [put invoker onboarding body]</li> <li>\"notificationDestination\": \"http://host.docker.internal:8086/netapp_new_callback\",</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li>Response to Update Request (PUT) with minor change must contain:<ol> <li>200 OK response.</li> <li>notificationDestination on response must contain the new value</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_invoker_management/#test-case-4-update-not-onboarded-network-app","title":"Test Case 4: Update Not Onboarded Network App","text":"<p>Test ID: capif_api_invoker_management-4</p> <p>Description:</p> <p>This test will try to update information of not onboarded Network App at CAPIF Core.</p> <p>Pre-Conditions:</p> <ul> <li>Network App was registered previously</li> <li>Network App was not onboarded previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker at CCF</li> <li>Onboard Invoker at CCF</li> <li>Update Onboarding Information at CCF of not onboarded</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Update information of not onboarded Invoker:</p> <ul> <li>Send PUT to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}</li> <li>Reference Request Body is: [put invoker onboarding body]</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> </ol> </li> <li>Response to Update Request (PUT) must contain:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Please provide an existing Network App ID\".</li> <li>cause with message \"Not exist Network App ID\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_invoker_management/#test-case-5-offboard-network-app","title":"Test Case 5: Offboard Network App","text":"<p>Test ID: capif_api_invoker_management-5</p> <p>Description:</p> <p>This test case will check that a Registered Network App can be deleted.</p> <p>Pre-Conditions:</p> <ul> <li>Network App was registered previously</li> <li>Network App was onboarded previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker at CCF</li> <li>Onboard Invoker at CCF</li> <li>Offboard Invoker at CCF</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Offboard:</p> <ul> <li>Send DELETE to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> </ol> </li> <li>Response to Offboard Request (DELETE) must contain:<ol> <li>204 No Content</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_invoker_management/#test-case-6-offboard-not-previsouly-onboarded-network-app","title":"Test Case 6: Offboard Not previsouly Onboarded Network App","text":"<p>Test ID: capif_api_invoker_management-6</p> <p>Description:</p> <p>This test case will check that a Non-Registered Network App cannot be deleted</p> <p>Pre-Conditions:</p> <ul> <li>Network App was registered previously</li> <li>Network App was not onboarded previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker at CCF</li> <li>Offboard Invoker at CCF</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Offboard:</p> <ul> <li>Send DELETE to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Offboard Request (DELETE) must contain:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Please provide an existing Network App ID\".</li> <li>cause with message \"Not exist Network App ID\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_invoker_management/#test-case-7-update-onboarded-network-app-certificate","title":"Test Case 7: Update Onboarded Network App Certificate","text":"<p>Test ID: capif_api_invoker_management-7</p> <p>Description:</p> <p>This test will try to update public key and get a new signed certificate by CAPIF Core.</p> <p>Pre-Conditions:</p> <ul> <li>Network App was registered previously</li> <li>Network App was onboarded previously with {onboardingId} and {public_key_1}</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Invoker at CCF</li> <li>Onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Update Onboarding Information at CCF with new public key</li> <li>Update Onboarding Information at CCF with minor change</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding with public_key_1.</p> </li> <li> <p>Create {public_key_2}</p> </li> <li> <p>Update information of previously onboarded Invoker:</p> <ul> <li>Send PUT to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</li> <li>Reference Request Body is: [put invoker onboarding body]</li> <li>[\"onboardingInformation\"][\"apiInvokerPublicKey\"]: {public_key_2},</li> <li>Store new certificate.</li> </ul> </li> <li> <p>Update information of previously onboarded Invoker Using new certificate:</p> <ul> <li>Send PUT to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</li> <li>Reference Request Body is: [put invoker onboarding body]</li> <li>\"notificationDestination\": \"http://host.docker.internal:8086/netapp_new_callback\",</li> <li>Use new Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Onboard request must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> <li>Response to Update Request (PUT) with new public key:<ol> <li>200 OK response.</li> <li>apiInvokerCertificate with new certificate on response -&gt; store to use.</li> </ol> </li> <li>Response to Update Request (PUT) with minor change must contain:<ol> <li>200 OK response.</li> <li>notificationDestination on response must contain the new value</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_logging_service/","title":"Test Plan for CAPIF Api Logging Service","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_logging_service/#test-case-1-creates-a-new-individual-capif-log-entry","title":"Test Case 1: Creates a new individual CAPIF Log Entry.","text":"<p>Test ID: capif_api_logging-1</p> <p>Description:</p> <p>This test case will check that a CAPIF AEF can create log entry to Logging Service</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is pre-authorised (has valid aefId from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding and invoker onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Log Entry:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body log entry request body</li> <li>Use AEF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>201 Created</li> <li>Response Body must follow InvocationLog data structure with:<ul> <li>aefId</li> <li>apiInvokerId</li> <li>logs</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invocation-logs/v1/{aefId}/logs/{logId}</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_logging_service/#test-case-2-creates-a-new-individual-capif-log-entry-with-invalid-aefid","title":"Test Case 2:  Creates a new individual CAPIF Log Entry with Invalid aefId","text":"<p>Test ID: capif_api_logging-2</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is not pre-authorised (has not valid aefId from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding and invoker onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Log Entry:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{not-valid-aefId}/logs</li> <li>body log entry request body</li> <li>Use AEF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Exposer not exist\".</li> <li>cause with message \"Exposer id not found\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_logging_service/#test-case-3-creates-a-new-individual-capif-log-entry-with-invalid-serviceapi","title":"Test Case 3:  Creates a new individual CAPIF Log Entry with Invalid serviceAPI","text":"<p>Test ID: capif_api_logging-3</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority)</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding and invoker onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Log Entry:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body [log entry request body with serviceAPI apiName apiId not valid]</li> <li>Use AEF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker not exist\".</li> <li>cause with message \"Invoker id not found\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_logging_service/#test-case-4-creates-a-new-individual-capif-log-entry-with-invalid-apiinvokerid","title":"Test Case 4:  Creates a new individual CAPIF Log Entry with Invalid apiInvokerId","text":"<p>Test ID: capif_api_logging-4</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority)</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding and invoker onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Log Entry:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body [log entry request body with invokerId not valid]</li> <li>Use AEF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created response.</li> <li>body returned must accomplish APIProviderEnrolmentDetails data structure.</li> <li>For each apiProvFuncs, we must check:<ol> <li>apiProvFuncId is set</li> <li>apiProvCert under regInfo is set properly</li> </ol> </li> <li>Location Header must contain the new resource URL {apiRoot}/api-provider-management/v1/registrations/{registrationId}</li> </ol> </li> <li> <p>Response to Logging Service must accomplish:</p> <ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker not exist\".</li> <li>cause with message \"Invoker id not found\".</li> </ul> </li> </ol> </li> <li> <p>Log Entry are not stored in CAPIF Database</p> </li> </ol>"},{"location":"testing/testplan/api_logging_service/#test-case-5-creates-a-new-individual-capif-log-entry-with-invalid-aefid-in-body","title":"Test Case 5:  Creates a new individual CAPIF Log Entry with Invalid aefId in body","text":"<p>Test ID: capif_api_logging-5</p> <p>Description:</p> <p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId in body</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF provider is pre-authorised (has valid apfId from CAPIF Authority)</li> <li>Service exist in CAPIF</li> <li>Invoker exist in CAPIF</li> </ul> <p>Execution Steps:   1. Register Provider and Invoker CCF   2. Publish Service   3. Create Log Entry</p> <p>Information of Test:</p> <ol> <li> <p>Perform provider onboarding and invoker onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Log Entry:</p> <ol> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</li> <li>body [log entry request body with bad aefId] </li> <li>Use AEF Certificate</li> </ol> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Logging Service must accomplish:<ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"AEF id not matching in request and body\".</li> <li>cause with message \"Not identical AEF id\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/","title":"Test Plan for CAPIF Api Provider Management","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_provider_management/#test-case-1-register-api-provider","title":"Test Case 1: Register Api Provider","text":"<p>Test ID: capif_api_provider_management-1</p> <p>Description:</p> <p>This test case will check that Api Provider can be registered con CCF</p> <p>Pre-Conditions:</p> <ul> <li>Provider is pre-authorised (has valid certificate from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Create private and public key for provider and each function to register.</li> <li>Register Provider.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Store each cert in a file with according name.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Register Provider at Provider Management:<ol> <li>201 Created response.</li> <li>body returned must accomplish APIProviderEnrolmentDetails data structure.</li> <li>For each apiProvFuncs, we must check:<ol> <li>apiProvFuncId is set</li> <li>apiProvCert under regInfo is set properly</li> </ol> </li> <li>Location Header must contain the new resource URL {apiRoot}/api-provider-management/v1/registrations/{registrationId}</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/#test-case-2-register-api-provider-already-registered","title":"Test Case 2: Register Api Provider Already registered","text":"<p>Test ID: capif_api_provider_management-2</p> <p>Description:</p> <p>This test case will check that a Api Provider previously registered cannot be re-registered</p> <p>Pre-Conditions:</p> <ul> <li>Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB</li> </ul> <p>Execution Steps:</p> <ol> <li>Create private and public key for provider and each function to register.</li> <li>Register Provider.</li> <li>Re-Register Provider.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Store each cert in a file with according name.</li> </ul> </li> <li> <p>Re-Register Provider:</p> <ul> <li>Same regSec than Previous registration</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Re-Register Provider:<ol> <li>403 Forbidden response.</li> <li> <p>body returned must accomplish ProblemDetails data structure, with:</p> <ul> <li>status 403</li> <li>title with message \"Forbidden\"</li> <li>detail with message \"Provider already registered\".</li> <li>cause with message \"Identical provider reg sec\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/#test-case-3-update-registered-api-provider","title":"Test Case 3: Update Registered Api Provider","text":"<p>Test ID: capif_api_provider_management-3</p> <p>Description:</p> <p>This test case will check that a Registered Api Provider can be updated</p> <p>Pre-Conditions:</p> <ul> <li>Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB</li> </ul> <p>Execution Steps:</p> <ol> <li>Create private and public key for provider and each function to register.</li> <li>Register Provider</li> <li>Update Provider</li> </ol> <p>Information of Test:</p> <ol> <li>Create public and private key at provider for provider itself and each function (apf, aef and amf)</li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Get Resource URL from Location</li> </ul> </li> <li> <p>Update Provider:</p> <ul> <li>Send PUT to Resource URL returned at registration https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}</li> <li>body provider request body with apiProvDomInfo set to ROBOT_TESTING_MOD</li> <li>Use AMF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Register Provider:</p> <ol> <li>201 Created response.</li> <li>body returned must accomplish APIProviderEnrolmentDetails data structure.</li> <li>Location Header must contain the new resource URL {apiRoot}/api-provider-management/v1/registrations/{registrationId}</li> </ol> </li> <li> <p>Update Provider:</p> <ol> <li>200 OK response.</li> <li>body returned must accomplish APIProviderEnrolmentDetails data structure, with:<ul> <li>apiProvDomInfo set to ROBOT_TESTING_MOD</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/#test-case-4-update-not-registered-api-provider","title":"Test Case 4: Update Not Registered Api Provider","text":"<p>Test ID: capif_api_provider_management-4</p> <p>Description:</p> <p>This test case will check that a Non-Registered Api Provider cannot be updated</p> <p>Pre-Conditions:</p> <ul> <li>Api Provider was not registered previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Update Not Registered Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Store each cert in a file with according name.</li> </ul> </li> <li> <p>Update Not Registered Provider:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}</li> <li>body provider request body</li> <li>Use AMF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Update Not Registered Provider:<ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Not Exist Provider Enrolment Details\".</li> <li>cause with message \"Not found registrations to Send THIS api provider details\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/#test-case-5-partially-update-registered-api-provider","title":"Test Case 5: Partially Update Registered Api Provider","text":"<p>Test ID: capif_api_provider_management-5</p> <p>Description:</p> <p>This test case will check that a Registered Api Provider can be partially updated</p> <p>Pre-Conditions:</p> <ul> <li>Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Register Provider</li> <li>Partial update provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Store each cert in a file with according name.</li> </ul> </li> <li> <p>Partial update provider:</p> <ul> <li>Send PATCH https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}</li> <li>body provider request patch body</li> <li>Use AMF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Partial update provider at Provider Management:<ol> <li>200 OK response.</li> <li>body returned must accomplish APIProviderEnrolmentDetails data structure, with:<ul> <li>apiProvDomInfo with \"ROBOT_TESTING_MOD\"</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/#test-case-6-partially-update-not-registered-api-provider","title":"Test Case 6: Partially Update Not Registered Api Provider","text":"<p>Test ID: capif_api_provider_management-6</p> <p>Description:</p> <p>This test case will check that a Non-Registered Api Provider cannot be partially updated  </p> <p>Pre-Conditions:</p> <ul> <li>Api Provider was not registered previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Register Provider</li> <li>Partial update provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Store each cert in a file with according name.</li> </ul> </li> <li> <p>Partial update Provider:</p> <ul> <li>Send PATCH https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_API_PROVIDER_NOT_REGISTERED}</li> <li>body provider request patch body</li> <li>Use AMF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Partial update provider:<ol> <li>404 Not Found response.</li> <li> <p>body returned must accomplish ProblemDetails data structure, with:</p> <ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Not Exist Provider Enrolment Details\".</li> <li>cause with message \"Not found registrations to Send THIS api provider details\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/#test-case-7-delete-registered-api-provider","title":"Test Case 7: Delete Registered Api Provider","text":"<p>Test ID: capif_api_provider_management-7</p> <p>Description:</p> <p>This test case will check that a Registered Api Provider can be deleted</p> <p>Pre-Conditions:</p> <ul> <li>Api Provider was registered previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Register Provider</li> <li>Delete Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Store each cert in a file with according name.</li> </ul> </li> <li> <p>Delete registered provider:</p> <ul> <li>Send DELETE https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}</li> <li>Use AMF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Delete Provider:<ol> <li>204 No Content response.</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_provider_management/#test-case-8-delete-not-registered-api-provider","title":"Test Case 8: Delete Not Registered Api Provider","text":"<p>Test ID: capif_api_provider_management-8</p> <p>Description:</p> <p>This test case will check that a Non-Registered Api Provider cannot be deleted</p> <p>Pre-Conditions:</p> <ul> <li>Api Provider was not registered previously</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Delete Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p> </li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Authentication Bearer with access_token</li> <li>Store each cert in a file with according name.</li> </ul> </li> <li> <p>Delete registered provider at Provider Management:</p> <ul> <li>Send DELETE https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}</li> <li>Use AMF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Delete Provider:<ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Not Exist Provider Enrolment Details\".</li> <li>cause with message \"Not found registrations to Send THIS api provider details\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/","title":"Test Plan for CAPIF Api Publish Service","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_publish_service/#test-case-1-publish-api-by-authorised-api-publisher","title":"Test Case 1: Publish API by Authorised API Publisher","text":"<p>Test ID: capif_api_publish_service-1</p> <p>Description:</p> <p>This test case will check that an API Publisher can Publish an API</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li> <p>Register Provider at CCF and store certificates.</p> </li> <li> <p>Publish Service API</p> </li> <li> <p>Retrieve {apiId} from body and Location header with new resource created from response</p> </li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> </li> <li> <p>Send POST to ccf_publish_url: https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</p> </li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Published Service API is stored in CAPIF Database</p> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-2-publish-api-by-non-authorised-api-publisher","title":"Test Case 2: Publish API by NON Authorised API Publisher","text":"<p>Test ID: capif_api_publish_service-2</p> <p>Description:</p> <p>This test case will check that an API Publisher cannot Publish an API withot valid apfId </p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Publish Service API with invalid APF ID</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API with invalid APF ID at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Publisher not existing\".</li> <li>cause with message \"Publisher id not found\".</li> </ul> </li> </ol> </li> <li> <p>Service API is NOT stored in CAPIF Database</p> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-3-retrieve-all-apis-published-by-authorised-apfid","title":"Test Case 3: Retrieve all APIs Published by Authorised apfId","text":"<p>Test ID: capif_api_publish_service-3</p> <p>Description:</p> <p>This test case will check that an API Publisher can Retrieve all API published</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li> <li>At least 2 service APIs are published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Publish Service API service_1</li> <li>Retrieve {apiId1} from body and Location header with new resource created from response</li> <li>Publish Service API service_2</li> <li>Retrieve {apiId2} from body and Location header with new resource created from response</li> <li>Retrieve All published APIs and check if both are present.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Publish Other Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_2</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Retrieve all published APIs:</p> <ul> <li>Send GET to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to service 1 Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}</li> </ol> </li> <li> <p>Response to service 2 Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}</li> </ol> </li> <li> <p>Published Service APIs are stored in CAPIF Database</p> </li> <li> <p>Response to Retrieve all published APIs:</p> <ol> <li>200 OK</li> <li>Response body must return an array of ServiceAPIDescription data.</li> <li>Array must contain all previously published APIs.</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-4-retrieve-all-apis-published-by-non-authorised-apfid","title":"Test Case 4: Retrieve all APIs Published by NON Authorised apfId","text":"<p>Test ID: capif_api_publish_service-4</p> <p>Description:</p> <p>This test case will check that an API Publisher cannot Retrieve API published when apfId is not authorised </p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Retrieve All published APIs</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Retrieve all published APIs:</p> <ul> <li>Send GET to https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>401 Non Authorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Provider not existing\".</li> <li>cause with message \"Provider id not found\".</li> </ul> </li> </ol> </li> <li> <p>Service API is NOT stored in CAPIF Database</p> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-5-retrieve-single-apis-published-by-authorised-apfid","title":"Test Case 5: Retrieve single APIs Published by Authorised apfId","text":"<p>Test ID: capif_api_publish_service-5</p> <p>Description:</p> <p>This test case will check that an API Publisher can Retrieve API published one by one</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li> <li>At least 2 service APIs are published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Publish Service API service_1.</li> <li>Retrieve {apiId1} from body and Location header with new resource created from response.</li> <li>Publish Service API service_2.</li> <li>Retrieve {apiId2} from body and Location header with new resource created from response.</li> <li>Retrieve service_1 API Detail.</li> <li>Retrieve service_2 API Detail.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Publish Other Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_2</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Retrieve service_1 published APIs detail:</p> <ul> <li>Send GET to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId1}</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Retrieve service_2 published APIs detail:</p> <ul> <li>Send GET to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId2}</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to service 1 Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}</li> </ol> </li> <li> <p>Response to service 2 Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}</li> </ol> </li> <li> <p>Published Service APIs are stored in CAPIF Database</p> </li> <li> <p>Response to Retrieve service_1 published API using apiId1:</p> <ol> <li>200 OK</li> <li>Response body must return a ServiceAPIDescription data.</li> <li>Array must contain same information than service_1 published registration response.</li> </ol> </li> <li> <p>Response to Retrieve service_2 published API using apiId2:</p> <ol> <li>200 OK</li> <li>Response body must return a ServiceAPIDescription data.</li> <li>Array must contain same information than service_2 published registration response.</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-6-retrieve-single-apis-non-published-by-authorised-apfid","title":"Test Case 6: Retrieve single APIs non Published by Authorised apfId","text":"<p>Test ID: capif_api_publish_service-6</p> <p>Description:</p> <p>This test case will check that an API Publisher try to get detail of not published api.</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li> <li>No published api</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Retrieve not published API Detail.</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration</li> <li>Retrieve not published APIs detail:<ul> <li>Send GET to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Retrieve for NOT published API must accomplish:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Service API not found\".</li> <li>cause with message \"No Service with specific credentials exists\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-7-retrieve-single-apis-published-by-non-authorised-apfid","title":"Test Case 7: Retrieve single APIs Published by NON Authorised apfId","text":"<p>Test ID: capif_api_publish_service-7</p> <p>Description:</p> <p>This test case will check that an API Publisher cannot Retrieve detailed API published when apfId is not authorised </p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Publish Service API at CCF</li> <li>Retrieve {apiId} from body and Location header with new resource created from response.</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Invoker Certificate</li> <li>Retrieve detailed published API acting as Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Retrieve detailed published APIs:</p> <ul> <li>Send GET to https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/${apiId}</li> <li>Use Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Retrieve Detailed published API acting as Invoker must accomplish:</p> <ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"User not authorized\".</li> <li>cause with message \"Certificate not authorized\".</li> </ul> </li> </ol> </li> <li> <p>Service API is NOT stored in CAPIF Database</p> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-8-update-api-published-by-authorised-apfid-with-valid-serviceapiid","title":"Test Case 8: Update API Published by Authorised apfId with valid serviceApiId","text":"<p>Test ID: capif_api_publish_service-8</p> <p>Description:</p> <p>This test case will check that an API Publisher can Update published API with a valid serviceApiId </p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li> <li>A service APIs is published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Publish Service API</li> <li>Retrieve {apiId} from body and Location header with new resource url created from response</li> <li>Update published Service API.</li> <li>Retrieve detail of Service API</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>get resource url from location Header.</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Update published API at CCF:</p> <ul> <li>Send PUT to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</li> <li>body service api description with overrided apiName to service_1_modified</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Retrieve detail of service API:</p> <ul> <li>Send GET to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</li> <li>check apiName is service_1_modified</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Response to Update Published Service API:</p> <ol> <li>200 OK</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiName service_1_modified</li> </ul> </li> </ol> </li> <li> <p>Response to Retrieve detail of Service API:</p> <ol> <li>200 OK</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiName service_1_modified.</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-9-update-apis-published-by-authorised-apfid-with-invalid-serviceapiid","title":"Test Case 9: Update APIs Published by Authorised apfId with invalid serviceApiId","text":"<p>Test ID: capif_api_publish_service-9</p> <p>Description:</p> <p>This test case will check that an API Publisher cannot Update published API with a invalid serviceApiId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Update published Service API.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Update published API at CCF:</p> <ul> <li>Send PUT to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</li> <li>body service api description with overrided apiName to service_1*_modified*</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Response to Update Published Service API:</p> <ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Service API not found\".</li> <li>cause with message \"Service API id not found\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-10-update-apis-published-by-non-authorised-apfid","title":"Test Case 10: Update APIs Published by NON Authorised apfId","text":"<p>Test ID: capif_api_publish_service-10</p> <p>Description:</p> <p>This test case will check that an API Publisher cannot Update API published when apfId is not authorised</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Publish Service API at CCF</li> <li>Retrieve {apiId} from body and Location header with new resource created from response.</li> <li>Register and onboard Invoker at CCF</li> <li>Store signed Invoker Certificate</li> <li>Update published API at CCF as Invoker</li> <li>Retrieve detail of Service API as publisher</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Update published API at CCF:</p> <ul> <li>Send PUT to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> <li>body service api description with overrided apiName to service_1*_modified*</li> <li>Use Invoker Certificate</li> </ul> </li> <li> <p>Retrieve detail of service API:</p> <ul> <li>Send GET to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</li> <li>check apiName is service_1</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Update published API acting as Invoker must accomplish:</p> <ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"User not authorized\".</li> <li>cause with message \"Certificate not authorized\".</li> </ul> </li> </ol> </li> <li> <p>Response to Retrieve Detail of Service API:</p> <ol> <li>200 OK</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiName service_1.</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-11-delete-api-published-by-authorised-apfid-with-valid-serviceapiid","title":"Test Case 11: Delete API Published by Authorised apfId with valid serviceApiId","text":"<p>Test ID: capif_api_publish_service-11</p> <p>Description:</p> <p>This test case will check that an API Publisher can Delete published API with a valid serviceApiId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority).</li> <li>A service APIs is published.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Publish Service API</li> <li>Retrieve {apiId} from body and Location header with new resource created from response</li> <li>Remove published API at CCF</li> <li>Try to retreive deleted service API from CCF</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Remove published Service API at CCF:</p> <ul> <li>Send DELETE to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> <li>Use APF Certificate</li> </ul> </li> <li>Retrieve detail of service API:<ul> <li>Send GET to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Response to Publish request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow ServiceAPIDescription data structure with:<ul> <li>apiId</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</li> </ol> </li> <li> <p>Published Service API is stored in CAPIF Database</p> </li> <li> <p>Response to Remove published Service API at CCF:</p> <ol> <li>204 No Content</li> </ol> </li> <li> <p>Response to Retrieve for DELETED published API must accomplish:</p> <ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Service API not found\".</li> <li>cause with message \"No Service with specific credentials exists\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-12-delete-apis-published-by-authorised-apfid-with-invalid-serviceapiid","title":"Test Case 12: Delete APIs Published by Authorised apfId with invalid serviceApiId","text":"<p>Test ID: capif_api_publish_service-12</p> <p>Description:</p> <p>This test case will check that an API Publisher cannot Delete with invalid serviceApiId</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority).</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Remove published API at CCF with invalid serviceId</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Remove published Service API at CCF with invalid serviceId:</p> <ul> <li>Send DELETE to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</li> <li>Use APF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Remove published Service API at CCF:<ol> <li>404 Not Found</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Service API not found\".</li> <li>cause with message \"Service API id not found\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_publish_service/#test-case-13-delete-apis-published-by-non-authorised-apfid","title":"Test Case 13: Delete APIs Published by NON Authorised apfId","text":"<p>Test ID: capif_api_publish_service-12</p> <p>Description:</p> <p>This test case will check that an API Publisher cannot Delete API published when apfId is not authorised</p> <p>Pre-Conditions:</p> <ul> <li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority).</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF and store certificates.</li> <li>Register Invoker and onboard Invoker at CCF</li> <li>Remove published API at CCF with invalid serviceId as Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body service api description with apiName service_1</li> <li>Get apiId</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Remove published Service API at CCF with invalid serviceId as Invoker:</p> <ul> <li>Send DELETE to resource URL https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</li> <li>Use Invoker Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Remove published Service API at CCF:<ol> <li>401 Unauthorized</li> <li>Error Response Body must accomplish with ProblemDetails data structure with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"User not authorized\".</li> <li>cause with message \"Certificate not authorized\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/","title":"Test Plan for CAPIF Api Security Service","text":"<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>"},{"location":"testing/testplan/api_security_service/#test-case-1-create-a-security-context-for-an-api-invoker","title":"Test Case 1: Create a security context for an API invoker","text":"<p>Test ID: capif_security_api-1</p> <p>Description:</p> <p>This test case will check that an API Invoker can create a Security context</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Invoker Onboarding</li> <li>Create Security Context for this Invoker<ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Create security context:<ol> <li>201 Created response.</li> <li>body returned must accomplish ServiceSecurity data structure.</li> <li>Location Header must contain the new resource URL {apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-2-create-a-security-context-for-an-api-invoker-with-provider-role","title":"Test Case 2: Create a security context for an API invoker with Provider role","text":"<p>Test ID:: capif_security_api-2</p> <p>Description:</p> <p>This test case will check that an Provider cannot create a Security context with valid apiInvokerId.</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context using Provider certificate</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker but using Provider certificate.</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Create security context using Provider certificate:</p> <ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be invoker\".</li> </ul> </li> </ol> </li> <li> <p>No context stored at DB</p> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-3-create-a-security-context-for-an-api-invoker-with-provider-entity-role-and-invalid-apiinvokerid","title":"Test Case 3: Create a security context for an API invoker with Provider entity role and invalid apiInvokerId","text":"<p>Test ID:: capif_security_api-3</p> <p>Description:</p> <p>This test case will check that an Provider cannot create a Security context with invalid apiInvokerID.</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Create Security Context using Provider certificate</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Create Security Context for this not valid apiInvokerId and using Provider certificate.</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</li> <li>body service security body</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Create security context using Provider certificate:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be invoker\".</li> </ul> </li> </ol> </li> <li>No context stored at DB</li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-4-create-a-security-context-for-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid","title":"Test Case 4: Create a security context for an API invoker with Invoker entity role and invalid apiInvokerId","text":"<p>Test ID:: capif_security_api-4</p> <p>Description:</p> <p>This test case will check that an Invoker cannot create a Security context with valid apiInvokerId.</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with invalid apiInvokerId</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Create Security Context using Provider certificate</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</li> <li>body service security body</li> <li>Use Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Create security context using Provider certificate:</p> <ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker not found\".</li> <li>cause with message \"API Invoker not exists or invalid ID\".</li> </ul> </li> </ol> </li> <li> <p>No context stored at DB</p> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-5-retrieve-the-security-context-of-an-api-invoker","title":"Test Case 5: Retrieve the Security Context of an API Invoker","text":"<p>Test ID:: capif_security_api-5</p> <p>Description:</p> <p>This test case will check that an provider can retrieve the Security context of an API Invoker</p> <p>Pre-Conditions:</p> <ul> <li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context using Provider certificate</li> <li>Retrieve Security Context by Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker.</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Retrieve Security Context of Invoker by Provider:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Retrieve security context:<ol> <li>200 OK response.</li> <li>body returned must accomplish ServiceSecurity data structure.</li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-6-retrieve-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid","title":"Test Case 6: Retrieve the Security Context of an API Invoker with invalid apiInvokerID","text":"<p>Test ID:: capif_security_api-6</p> <p>Description:</p> <p>This test case will check that an provider can retrieve the Security context of an API Invoker</p> <p>Pre-Conditions:</p> <ul> <li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Create Security Context using Provider certificate</li> <li>Retrieve Security Context by Provider of invalid invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Retrieve Security Context of invalid Invoker by Provider:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</li> <li>Using AEF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Retrieve security context:<ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker not found\".</li> <li>cause with message \"API Invoker not exists or invalid ID\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-7-retrieve-the-security-context-of-an-api-invoker-with-invalid-apfid","title":"Test Case 7: Retrieve the Security Context of an API Invoker with invalid apfId","text":"<p>Test ID:: capif_security_api-7</p> <p>Description:</p> <p>This test case will check that an Provider cannot retrieve the Security context of an API Invoker without valid apfId</p> <p>Pre-Conditions:</p> <ul> <li>API Exposure Function is not pre-authorised (has invalid apfId)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Store signed Certificate</li> <li>Create Security Context</li> <li>Retrieve Security Context as Provider.</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Retrieve Security Context as Invoker role:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Create security context:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be aef\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-8-delete-the-security-context-of-an-api-invoker","title":"Test Case 8: Delete the Security Context of an API Invoker","text":"<p>Test ID:: capif_security_api-8</p> <p>Description:</p> <p>This test case will check that an Provider can delete a Security context</p> <p>Pre-Conditions:</p> <ul> <li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context using Provider certificate</li> <li>Delete Security Context by Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker but using Provider certificate.</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using AEF Certificate</li> </ul> </li> <li> <p>Delete Security Context of Invoker by Provider:</p> <ul> <li>Send DELETE https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Use AEF Certificate</li> </ul> </li> <li> <p>Retrieve Security Context of Invoker by Provider:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Delete security context:</p> <ol> <li>204 No Content response.</li> </ol> </li> <li> <p>Retrieve security context:</p> <ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Security context not found\".</li> <li>cause with message \"API Invoker not exists or invalid ID\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-9-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role","title":"Test Case 9: Delete the Security Context of an API Invoker with Invoker entity role","text":"<p>Test ID:: capif_security_api-9</p> <p>Description:</p> <p>This test case will check that an Invoker cannot delete a Security context</p> <p>Pre-Conditions:</p> <ul> <li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Create Security Context using Provider certificate</li> <li>Delete Security Context by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Delete Security Context of Invoker:</p> <ul> <li>Send DELETE https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Use Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Delete security context:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be aef\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-10-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid","title":"Test Case 10: Delete the Security Context of an API Invoker with Invoker entity role and invalid apiInvokerID","text":"<p>Test ID:: capif_security_api-10</p> <p>Description:</p> <p>This test case will check that an Invoker cannot delete a Security context with invalid </p> <p>Pre-Conditions:</p> <ul> <li>Invoker is pre-authorised.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Delete Security Context by invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Invoker Onboarding</p> </li> <li> <p>Delete Security Context of Invoker:</p> <ul> <li>Send DELETE https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</li> <li>Use Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Delete security context:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be aef\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-11-delete-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid","title":"Test Case 11: Delete the Security Context of an API Invoker with invalid apiInvokerID","text":"<p>Test ID:: capif_security_api-11</p> <p>Description:</p> <p>This test case will check that an Provider cannot delete a Security context of invalid apiInvokerId</p> <p>Pre-Conditions:</p> <ul> <li>Provider is pre-authorised (has valid apfId from CAPIF Authority).</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Delete Security Context by provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Delete Security Context of Invoker by Provider:</p> <ul> <li>Send DELETE https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</li> <li>Use AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Retrieve security context:<ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker not found\".</li> <li>cause with message \"API Invoker not exists or invalid ID\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-12-update-the-security-context-of-an-api-invoker","title":"Test Case 12: Update the Security Context of an API Invoker","text":"<p>Test ID:: capif_security_api-12</p> <p>Description:</p> <p>This test case will check that an API Invoker can update a Security context</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context By Invoker</li> <li>Update Security Context By Invoker</li> <li>Retrieve Security Context By Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> </ul> </li> <li> <p>Update Security Context of Invoker:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update</li> <li>body service security body but with notification destination modified to http://robot.testing2</li> <li>Using Invoker Certificate.</li> </ul> </li> <li> <p>Retrieve Security Context of Invoker by Provider:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Using AEF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Update security context:</p> <ol> <li>200 OK response.</li> <li>body returned must accomplish ServiceSecurity data structure.</li> </ol> </li> <li> <p>Retrieve security context:</p> <ol> <li>200 OK response.</li> <li>body returned must accomplish ServiceSecurity data structure.<ol> <li>Check is this returned object match with modified one.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-13-update-the-security-context-of-an-api-invoker-with-provider-entity-role","title":"Test Case 13: Update the Security Context of an API Invoker with Provider entity role","text":"<p>Test ID:: capif_security_api-13</p> <p>Description:</p> <p>This test case will check that an Provider cannot update a Security context</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized.</li> <li>Invoker has created the Security Context previously.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context</li> <li>Update Security Context as Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> </ul> </li> <li> <p>Update Security Context of Invoker by Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update</li> <li>body service security body but with notification destination modified to http://robot.testing2</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Update security context:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be invoker\". </li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-14-update-the-security-context-of-an-api-invoker-with-aef-entity-role-and-invalid-apiinvokerid","title":"Test Case 14: Update the Security Context of an API Invoker with AEF entity role and invalid apiInvokerId","text":"<p>Test ID:: capif_security_api-14</p> <p>Description:</p> <p>This test case will check that an Provider cannot update a Security context of invalid apiInvokerId</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized.</li> <li>Invoker has created the Security Context previously.</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF</li> <li>Update Security Context as Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration</p> </li> <li> <p>Update Security Context of Invoker by Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update</li> <li>body service security body</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Update security context:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be invoker\". </li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-15-update-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid","title":"Test Case 15: Update the Security Context of an API Invoker with invalid apiInvokerID","text":"<p>Test ID:: capif_security_api-15</p> <p>Description:</p> <p>This test case will check that an API Invoker cannot update a Security context not valid apiInvokerId</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Update Security Context</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Update Security Context of Invoker:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Retrieve security context:<ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker not found\".</li> <li>cause with message \"API Invoker not exists or invalid ID\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-16-revoke-the-authorization-of-the-api-invoker-for-apis","title":"Test Case 16: Revoke the authorization of the API invoker for APIs.","text":"<p>Test ID:: capif_security_api-16</p> <p>Description:</p> <p>This test case will check that a Provider can revoke the authorization for APIs</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context by Invoker</li> <li>Revoke Security Context by Provider</li> <li>Retrieve Security Context by Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context By Invoker:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Revoke Authorization by Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete</li> <li>body security notification body</li> <li>Using AEF Certificate.</li> </ul> </li> <li> <p>Retrieve Security Context by Provider:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Using AEF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Revoke Authorization:</p> <ol> <li>204 No Content response.</li> </ol> </li> <li> <p>Retrieve security context:</p> <ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Security context not found\".</li> <li>cause with message \"API Invoker has no security context\".</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-17-revoke-the-authorization-of-the-api-invoker-for-apis-without-valid-apfid","title":"Test Case 17: Revoke the authorization of the API invoker for APIs without valid apfID.","text":"<p>Test ID:: capif_security_api-17</p> <p>Description:</p> <p>This test case will check that an Invoker can't revoke the authorization for APIs</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context</li> <li>Revoke Security Context by invoker</li> <li>Retrieve Security Context</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> </ul> </li> <li> <p>Revoke Authorization by invoker:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete</li> <li>body security notification body</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Retrieve Security Context of Invoker by Provider:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>Using Provider Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Revoke Security Context by invoker:</p> <ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 401</li> <li>title with message \"Unauthorized\"</li> <li>detail with message \"Role not authorized for this API route\".</li> <li>cause with message \"User role must be provider\". </li> </ul> </li> </ol> </li> <li> <p>Retrieve security context:</p> <ol> <li>200 OK response.</li> <li>body returned must accomplish ServiceSecurity data structure.<ol> <li>Check is this returned object match with created one.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-18-revoke-the-authorization-of-the-api-invoker-for-apis-with-invalid-apiinvokerid","title":"Test Case 18: Revoke the authorization of the API invoker for APIs with invalid apiInvokerId.","text":"<p>Test ID:: capif_security_api-18</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register and onboard Invoker at CCF</li> <li>Register Provider at CCF</li> <li>Create Security Context</li> <li>Revoke Security Context by Provider</li> <li>Retrieve Security Context</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Create Security Context for this Invoker:</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> </ul> </li> <li> <p>Revoke Authorization by Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/delete</li> <li>body security notification body</li> <li>Using AEF Certificate.</li> </ul> </li> <li> <p>Retrieve Security Context of Invoker by Provider:</p> <ul> <li>Send GET https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}?authenticationInfo=true&amp;authorizationInfo=true</li> <li>This request will ask with parameter to retrieve authenticationInfo and authorizationInfo</li> <li>Using AEF Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li> <p>Revoke Security Context by invoker:</p> <ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails data structure, with:<ul> <li>status 404</li> <li>title with message \"Not Found\"</li> <li>detail with message \"Invoker not found\".</li> <li>cause with message \"API Invoker not exists or invalid ID\".</li> </ul> </li> </ol> </li> <li> <p>Retrieve security context:</p> <ol> <li>200 OK response.</li> <li>body returned must accomplish ServiceSecurity data structure.<ol> <li>Check is this return one object that match with created one.</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-19-retrieve-access-token","title":"Test Case 19: Retrieve access token","text":"<p>Test ID:: capif_security_api-19</p> <p>Description:</p> <p>This test case will check that an API Invoker can retrieve a security access token OAuth 2.0.</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerId)</li> <li>Service API of Provider is published</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by invoker:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{securityId}/token:</li> <li>body access token req body and example example</li> <li>securityId is apiInvokerId.</li> <li>grant_type=client_credentials.</li> <li>Create Scope properly for request: 3gpp#{aef_id}:{api_name}</li> <li>Using Invoker Certificate.</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>200 OK</li> <li>body must follow AccessTokenRsp with:<ol> <li>access_token present</li> <li>token_type=Bearer</li> </ol> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-20-retrieve-access-token-by-provider","title":"Test Case 20: Retrieve access token by Provider","text":"<p>Test ID:: capif_security_api-20</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by provider:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{securityId}/token:</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=client_credentials</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish AccessTokenErr data structure, with:<ul> <li>error unauthorized_client</li> <li>error_description=Role not authorized for this API route</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-21-retrieve-access-token-by-provider-with-invalid-apiinvokerid","title":"Test Case 21: Retrieve access token by Provider with invalid apiInvokerId","text":"<p>Test ID:: capif_security_api-21</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot retrieve a security access token without valid apiInvokerId</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Provider</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by provider:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token.</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=client_credentials</li> <li>Using AEF Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>401 Unauthorized response.</li> <li>body returned must accomplish AccessTokenErr data structure, with:<ul> <li>error unauthorized_client</li> <li>error_description=Role not authorized for this API route</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-22-retrieve-access-token-with-invalid-apiinvokerid","title":"Test Case 22: Retrieve access token with invalid apiInvokerId","text":"<p>Test ID:: capif_security_api-22</p> <p>Description:</p> <p>This test case will check that an API Invoker can't retrieve a security access token without valid apiInvokerId</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised (has valid apiInvokerId)</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li>Perform Provider Registration and Invoker Onboarding</li> <li>Publish Service API at CCF:<ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li>Request Discover Published APIs not filtered:<ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li>Create Security Context for this Invoker<ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li>Request Access Token by invoker:<ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token.</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=client_credentials</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>404 Not Found response.</li> <li>body returned must accomplish ProblemDetails29571 data structure, with:<ul> <li>status 404</li> <li>title Not Found</li> <li>detail Security context not found</li> <li>cause API Invoker has no security context</li> </ul> </li> </ol> </li> </ol> <p>NOTE: ProblemDetails29571 is the definition present for this request at swagger of ProblemDetails, and this is different from definition of ProblemDetails across other CAPIF Services</p>"},{"location":"testing/testplan/api_security_service/#test-case-23-retrieve-access-token-with-invalid-client_id","title":"Test Case 23: Retrieve access token with invalid client_id","text":"<p>Test ID:: capif_security_api-23</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot retrieve a security access token without valid client_id at body</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by invoker:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{securityId}/token.</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=client_credentials</li> <li>client_id is not-valid </li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>400 Bad Request response.</li> <li>body returned must accomplish AccessTokenErr data structure, with:<ul> <li>error invalid_client</li> <li>error_description=Client Id not found</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-24-retrieve-access-token-with-unsupported-grant_type","title":"Test Case 24: Retrieve access token with unsupported grant_type","text":"<p>Test ID:: capif_security_api-24</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot retrieve a security access token with unsupported grant_type</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by invoker:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{securityId}/token.</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=not_valid</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>400 Bad Request response.</li> <li>body returned must accomplish AccessTokenErr data structure, with:<ul> <li>error unsupported_grant_type</li> <li>error_description=Invalid value for <code>grant_type</code> \\(${grant_type}\\), must be one of \\['client_credentials'\\] - 'grant_type'</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-25-retrieve-access-token-with-invalid-scope","title":"Test Case 25: Retrieve access token with invalid scope","text":"<p>Test ID:: capif_security_api-25</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot retrieve a security access token with complete invalid scope</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by invoker:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{securityId}/token.</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=client_credentials</li> <li>scope=not-valid-scope</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>400 Bad Request response.</li> <li>body returned must accomplish AccessTokenErr data structure, with:<ul> <li>error invalid_scope</li> <li>error_description=The first characters must be '3gpp'</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-26-retrieve-access-token-with-invalid-aefid-at-scope","title":"Test Case 26: Retrieve access token with invalid aefid at scope","text":"<p>Test ID:: capif_security_api-26</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot retrieve a security access token with invalid aefId at scope</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by invoker:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{securityId}/token.</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=client_credentials</li> <li>scope=3gpp#1234:*service_1*</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>400 Bad Request response.</li> <li>body returned must accomplish AccessTokenErr data structure, with:<ul> <li>error invalid_scope</li> <li>error_description=One of aef_id not belongs of your security context</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/api_security_service/#test-case-27-retrieve-access-token-with-invalid-apiname-at-scope","title":"Test Case 27: Retrieve access token with invalid apiName at scope","text":"<p>Test ID:: capif_security_api-27</p> <p>Description:</p> <p>This test case will check that an API Exposure Function cannot retrieve a security access token with invalid apiName at scope</p> <p>Pre-Conditions:</p> <ul> <li>API Invoker is pre-authorised and Provider is also authorized</li> </ul> <p>Execution Steps:</p> <ol> <li>Register Provider at CCF, store certificates and Publish Service API service_1 at CCF</li> <li>Register and onboard Invoker at CCF</li> <li>Discover Service APIs by Invoker.</li> <li>Create Security Context According to Service APIs discovered.</li> <li>Request Access Token by Invoker</li> </ol> <p>Information of Test:</p> <ol> <li> <p>Perform Provider Registration and Invoker Onboarding</p> </li> <li> <p>Publish Service API at CCF:</p> <ul> <li>Send POST to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</li> <li>body [service api description] with apiName service_1</li> <li>Use APF Certificate</li> </ul> </li> <li> <p>Request Discover Published APIs not filtered:</p> <ul> <li>Send GET to ccf_discover_url https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</li> <li>Param api-invoker-id is mandatory</li> <li>Using Invoker Certificate</li> </ul> </li> <li> <p>Create Security Context for this Invoker</p> <ul> <li>Send PUT https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</li> <li>body service security body</li> <li>Using Invoker Certificate.</li> <li>Create Security Information Body with one securityInfo for each aef present at each serviceAPIDescription present at Discover.</li> </ul> </li> <li> <p>Request Access Token by invoker:</p> <ul> <li>Sent POST https://{CAPIF_HOSTNAME}/securities/{securityId}/token.</li> <li>body access token req body</li> <li>securityId is apiInvokerId</li> <li>grant_type=client_credentials</li> <li>scope=3gpp#{aef_id}:not-valid</li> <li>Using Invoker Certificate</li> </ul> </li> </ol> <p>Expected Result:</p> <ol> <li>Response to Request of Access Token:<ol> <li>400 Bad Request response.</li> <li>body returned must accomplish AccessTokenErr data structure, with:<ul> <li>error invalid_scope</li> <li>error_description=One of the api names does not exist or is not associated with the aef id provided</li> </ul> </li> </ol> </li> </ol>"},{"location":"testing/testplan/common_operations/","title":"Common Operations","text":""},{"location":"testing/testplan/common_operations/#register-new-user","title":"Register new user","text":"<p>In order to use OpenCAPIF we must add a new user. This new user can onboard/register any Invokers or Providers.</p> <p>That new user must be created by administrator of Register Service and with the credentials shared by administrator, the new user can get the access_token by requesting it to Register service.</p> <p>The steps to register a new user at Register Service are:</p>"},{"location":"testing/testplan/common_operations/#admin-create-user","title":"Admin create User","text":"<p>1) Login as Admin to get access_token:</p> <ul> <li>Send POST to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/login<ul> <li>Include basic Auth Header with Admin credentials</li> </ul> </li> <li>Get access_token and refresh_token from response</li> </ul> <p></p> <p>2) Create User:</p> <ul> <li>Send POST to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/createUser<ul> <li>Include Admin access_token in Authorization Bearer Header</li> <li>Body user_registration_body</li> </ul> </li> </ul> <p></p>"},{"location":"testing/testplan/common_operations/#user-retrieve-access-token-and-other-information","title":"User Retrieve access token and other information","text":"<p>1) Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth<ul> <li>Include basic Auth Header with User credentials</li> </ul> </li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> <p></p>"},{"location":"testing/testplan/common_operations/#onboard-an-invoker","title":"Onboard an Invoker","text":""},{"location":"testing/testplan/common_operations/#steps-to-perform-operation","title":"Steps to perform operation","text":"<p>Preconditions: The administrator must have previously registered the User.</p> <ol> <li>Create public and private key at invoker</li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Onboard Invoker:     </p> <ul> <li>Send POST to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers</li> <li>Reference Request Body: invoker onboarding body</li> <li>\"onboardingInformation\"-&gt;\"apiInvokerPublicKey\": must contain public key generated by Invoker.</li> <li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li> </ul> </li> </ol>"},{"location":"testing/testplan/common_operations/#checks-to-ensure-onboarding","title":"Checks to ensure onboarding","text":"<ol> <li> <p>Response to Get Auth:</p> <ol> <li>200 OK</li> <li>access_token returned.</li> </ol> </li> <li> <p>Response to Onboard request must accomplish:</p> <ol> <li>201 Created</li> <li>Response Body must follow APIInvokerEnrolmentDetails data structure with:<ul> <li>apiInvokerId</li> <li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li> </ul> </li> <li>Response Header Location must be received with URI to new resource created, following this structure: {apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</li> </ol> </li> </ol>"},{"location":"testing/testplan/common_operations/#example-flow","title":"Example Flow","text":""},{"location":"testing/testplan/common_operations/#register-a-provider","title":"Register a Provider","text":""},{"location":"testing/testplan/common_operations/#steps-to-perform-operation_1","title":"Steps to Perform operation","text":"<ol> <li>Create public and private key at provider for provider itself and each function (apf, aef and amf)</li> <li> <p>Retrieve access_token by User:</p> <ul> <li>Send GET to https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</li> <li>Include basic Auth Header with Admin user/password</li> <li>Retrieve access_token and the urls needed for next requests from response body user_getauth_response_body_example</li> </ul> </li> <li> <p>Register Provider:</p> <ul> <li>Send POST https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</li> <li>body provider request body</li> <li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li> <li>Store each cert in a file with according name.</li> </ul> </li> </ol>"},{"location":"testing/testplan/common_operations/#checks-to-ensure-provider-registration","title":"Checks to ensure provider registration","text":"<ol> <li> <p>Response to Register:</p> <ol> <li>201 Created</li> </ol> </li> <li> <p>Response to Get Auth:</p> <ol> <li>200 OK</li> <li>access_token returned.</li> </ol> </li> <li> <p>Register Provider at Provider Management:</p> <ol> <li>201 Created response.</li> <li>body returned must accomplish APIProviderEnrolmentDetails data structure.</li> <li>For each apiProvFuncs, we must check:<ol> <li>apiProvFuncId is set</li> <li>apiProvCert under regInfo is set properly</li> </ol> </li> <li>Location Header must contain the new resource URL {apiRoot}/api-provider-management/v1/registrations/{registrationId}</li> </ol> </li> </ol>"},{"location":"testing/testplan/common_operations/#example-flow_1","title":"Example Flow","text":""}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Index","text":"<p>Welcome to the ETSI TeraFlowSDN (TFS) Controller wiki!</p> <p>This wiki provides a walkthrough on how to prepare your environment for executing and contributing to the ETSI SDG TeraFlowSDN. Besides, it describes how to run some example experiments.</p>"},{"location":"#try-teraflowsdn-release-30","title":"Try TeraFlowSDN Release 3.0","text":"<p>The new release launched on April 24th, 2024 incorporates a number of new features, improvements, and bug resolutions. Try it by following the guides below, and feel free to give us your feedback. See the Release Notes.</p>"},{"location":"#requisites","title":"Requisites","text":"<p>The guides and walkthroughs below make some reasonable assumptions to simplify the deployment of the TFS controller, the execution of experiments and tests, and the development of new contributions. In particular, we assume:</p> <ul> <li>A physical server or virtual machine for running the TFS controller with the following minimum specifications (check section Configure your Machine for additional details):</li> <li>4 cores / vCPUs</li> <li>8 GB of RAM (10 GB of RAM if you want to develop)</li> <li>60 GB of disk (100 GB of disk if you want to develop)</li> <li>1 NIC card</li> <li>VSCode with the Remote SSH extension</li> <li>Working machine software:</li> <li>Ubuntu Server 22.04.4 LTS or Ubuntu Server 20.04.6 LTS</li> <li>MicroK8s v1.24.17</li> </ul> <p>Use the Wiki menu in the right side of this page to navigate through the various contents of this wiki.</p>"},{"location":"#guides-and-walkthroughs","title":"Guides and Walkthroughs","text":"<p>The following guides and walkthroughs are provided:</p> <ul> <li>1. Deployment Guide</li> <li>2. Development Guide</li> <li>3. Run Experiments</li> <li>4. Features and Bugs</li> <li>5. Supported SBIs and Network Elements</li> <li>6. Supported NBIs</li> <li>7. Supported Service Handlers</li> <li>8. Troubleshooting</li> </ul>"},{"location":"#tutorials-and-tfs-virtual-machine","title":"Tutorials and TFS Virtual Machine","text":"<p>This section provides access to the links and all the materials prepared for the tutorials and hackfests involving ETSI TeraFlowSDN.</p> <ul> <li>TFS Hackfest #3 (Castelldefels, 16-17 October 2023)</li> <li> <p>The link includes explanatory material on P4 for TeraFlowSDN, the set of guided walkthrough, and the details on the interactive sessions the participants addressed (and recordings), as well as a TFS Virtual Machine (Release 2.1).</p> </li> <li> <p>TFS Hackfest #2 (Madrid, 20-21 June 2023)</p> </li> <li> <p>The link includes explanatory material on gNMI and ContainerLab for TeraFlowSDN, the set of challenges the participants addressed (and recordings), as well as a TFS Virtual Machine (Pre-Release 2.1).</p> </li> <li> <p>OFC SC472 (San Diego, 6 March 2023)</p> </li> <li> <p>The link includes a tutorial-style slide deck, as well as a TFS Virtual Machine (Release 2).</p> </li> <li> <p>TFS Hackfest #1 (Amsterdam, 20 October 2022)</p> </li> <li>The link includes a tutorial-style slide deck (and recordings), as well as a TFS Virtual Machine (Pre-Release 2).</li> </ul>"},{"location":"#versions","title":"Versions","text":"<p>New versions of TeraFlowSDN are periodically released. Each release is properly tagged and a branch is kept for its future bug fixing, if needed.</p> <ul> <li>The branch master, points always to the latest stable version of the TeraFlowSDN controller.</li> <li>The branches release/X.Y.Z, point to the code for the different release versions indicated in branch name.</li> <li>Code in these branches can be considered stable, and no new features are planned.</li> <li>In case of bugs, point releases increasing revision number (Z) might be created.</li> <li>The main development branch is named as develop.</li> <li>Use with care! Might not be stable.</li> <li>The latest developments and contributions are added to this branch for testing and validation before reaching a release. </li> </ul> <p>To choose the appropriate branch, follow the steps described in 1.3. Deploy TeraFlowSDN &gt; Checkout the Appropriate Git Branch</p>"},{"location":"#events","title":"Events","text":"<p>Find here after the list of past and future TFS Events:</p> <ul> <li>ETSI TeraFlowSDN Events </li> </ul>"},{"location":"#contact","title":"Contact","text":"<p>If your environment does not fit with the proposed assumptions and you experience issues  preparing it to work with the ETSI TeraFlowSDN controller, contact the ETSI TeraFlowSDN  SDG team through Slack</p>"},{"location":"FAQ/","title":"Frequently Asked Questions (FAQ)","text":""},{"location":"FAQ/#does-the-user-have-to-develop-the-3-elements-of-the-provider-aef-amf-and-apf","title":"Does the user have to develop the 3 elements of the provider (AEF, AMF and APF)?","text":"<p>No, you only have to make the request to the \"/onboarding\" endpoint. In it you must specify a CSR for the AEF, APF and AMF and you will receive the certificates for each of them in the response.</p>"},{"location":"FAQ/#there-is-one-party-that-publishes-the-api-and-another-that-exposes-it-what-is-the-difference","title":"There is one party that publishes the API and another that exposes it, what is the difference?","text":"<p>There are different services, the APF, intended for publishing the APIs, and the AEF, intended so that the invoker can call it. The APF is what connects to the Capif Core Function to publish the service and when the service is up, you need the AEF service so that invokers can connect to it.</p>"},{"location":"FAQ/#before-publishing-an-api-do-you-have-to-be-registered-in-capif","title":"Before publishing an API, do you have to be registered in CAPIF?","text":"<p>Yes, before publishing an API you must register using the POST /register endpoint.</p>"},{"location":"FAQ/#where-is-the-registration-done","title":"Where is the registration done?","text":"<p>Registration is done in a REST API outside of the CAPIF specification taht we have implemented.</p>"},{"location":"FAQ/#is-the-username-and-password-chosen-by-the-user-when-registering-or-is-it-assigned-when-requesting-registration-to-capif-public-instance","title":"Is the username and password chosen by the user when registering or is it assigned when requesting registration to CAPIF public instance?","text":"<p>When you make the request to the \"/endpoint\" of register, you will be returned a username and a password determined by CAPIF.</p>"},{"location":"FAQ/#what-is-a-csr","title":"What is a CSR?","text":"<p>A CSR is a Certificate Signing Request. It is a generated data block where the certificate is planned to be installed and contains key information such as public key, organization, and location, and is used to request a certificate from a certificate authority (CA). In CAPIF, 3 CSRs are necessary to register a provider, for AEF, APF and AMF.</p>"},{"location":"FAQ/#when-doing-the-register_provider-where-can-i-find-the-csrs-that-are-generated","title":"When doing the register_provider where can I find the CSRs that are generated?","text":"<p>When using the \"register_provider\" command, if you add the \"debug\" option, it shows you a json with the data used to register the provider. There we can find in the body a list of 3 elements corresponding to AEF, APF and AMF. IN each of them, the apiProbPubKey field corresponds to the CSR.</p>"},{"location":"FAQ/#how-to-use-the-example-client-capif_invoker_gui","title":"How to use the example client (CAPIF_INVOKER_GUI)?","text":"<p>First you have to make a \"./run.sh host:port\" indicating the address of the public CAPIF. Once the Docker containers are up, you have to do a \"./terminal_to_py_netapp.sh\" and then a \"python main.py\". At this point we will find ourselves in a console with some predefined commands to use the Client. If we press tab twice it will bring up the list of available commands.</p>"},{"location":"FAQ/#where-is-the-capif-public-instance-located","title":"Where is the CAPIF public instance located?","text":"<p>The CAPIF public instance can be found at the following URLs: - capif.mobilesandbox.cloud:37211 (HTTPS) - capif.mobilesandbox.cloud:37212 (HTTP)</p>"},{"location":"FAQ/#do-you-have-to-publish-3-apis-one-for-each-instance","title":"Do you have to publish 3 APIs? one for each instance?","text":"<p>No, you only have to publish a single API but each component is responsible for a specific service, whether publishing or exposing.</p>"},{"location":"FAQ/#once-the-api-is-published-is-it-always-active-or-do-you-have-to-republish-it-every-time-you-want-to-use-it","title":"Once the API is published, is it always active? Or do you have to republish it every time you want to use it?","text":"<p>It is better to unsubscribe the API every time you exit the application since otherwise it could be republished and it would be double.</p>"},{"location":"FAQ/#would-the-same-username-and-password-be-valid-for-different-invokers","title":"Would the same username and password be valid for different invokers?","text":"<p>Yes, a user can have multiple invokers at the same time, and as such, the username and password would be the same.</p>"},{"location":"FAQ/#what-is-the-notfication-destination-field-in-the-register_invoker-request","title":"What is the notfication destination field in the register_invoker request?","text":"<p>This is the callback URL used to notify events. CAPIF has an Event service to subscribe to that notifies actions such as a subscription to an API, a change in the state of an API...</p>"},{"location":"FAQ/#is-the-notification_destination-a-required-field-in-the-register_invoker","title":"Is the notification_destination a required field in the register_invoker","text":"<p>No, it is not mandatory, but if you do not enter it you will not receive any CAPIF events. For example, the APF may delete the API, you will not be notified that the API is no longer available.</p>"},{"location":"FAQ/#what-is-the-purpose-of-the-discover_service-function-in-the-invoker-client","title":"What is the purpose of the \"discover_service\" function in the invoker client?","text":"<p>The discover_service returns a json with all the services that exist exposed in CAPIF at that moment.</p>"},{"location":"FAQ/#what-is-the-purpose-of-the-get_security_auth-function-in-the-invoker-client","title":"What is the purpose of the \"get_security_auth\" function in the invoker client?","text":"<p>Sirve para pedir el token o para refrescarlo en caso de que haya caducado. You have to use that token to call the API from the invoker.</p>"},{"location":"FAQ/#what-is-the-purpose-of-the-register_security_context-function-in-the-invoker-client","title":"What is the purpose of the \"register_security_context\" function in the invoker client?","text":"<p>To consume the API it is necessary to have a Security Context registered with the data and the authentication method.</p>"},{"location":"FAQ/#is-a-user-the-same-as-an-exposer","title":"Is a user the same as an exposer?","text":"<p>No, a user registers in CAPIF and once done can have the role of invoker, provider or both.</p>"},{"location":"FAQ/#where-can-i-put-my-endpoint","title":"Where can I put my endpoint?","text":"<p>You have to set your endpoint when doing the \"publish_service\" functionality: <code>publish_service capif_ops/config_files/service_api_description_hello.json</code></p> <p>In the file \"service_api_description_hello.json\" you configure the service that is going to be exposed and by developing one to suit you, you expose your API.</p>"},{"location":"architecture/","title":"Architecture","text":""},{"location":"architecture/#architecture","title":"Architecture","text":"<p>The CAPIF architecture has three main components, Register Service, Vault and CCF, which are represented in the following image:</p> <p></p> <p>Each component is separated into different namespaces and all communications between them use Rest APIs.</p> <p>Apart from the communication between components, there are 2 other entities that can use them:</p> <ul> <li>Admin/superadmin: Responsible for managing users with the Register or carrying out special operations in the CCF.</li> <li>Users: They are those who want to use CAPIF, registering as a user in the Register and as Invoker or Provider in the CCF.</li> </ul>"},{"location":"architecture/#register-ns","title":"Register NS","text":"<p>This namespace belongs to the Register service, and we find 2 components:</p> <ul> <li>Register Service: It is responsible for managing all users who use CAPIF, in addition to providing the necessary information for its use.</li> <li>Register MONGO DATABASE: It is the Register database, in it we store all the information about registered users.</li> </ul>"},{"location":"architecture/#vault-ns","title":"Vault NS","text":"<p>This namespace belongs to Vault. </p> <p>This component is responsible for managing all CAPIF certificates, so other components such as the Register or the CCF communicate with it to create new certificates or request keys.</p>"},{"location":"architecture/#mon-ns","title":"Mon NS","text":"<p>This is the main namespace of CAPIF, since it contains all the CCF services in addition to other components:</p> <ul> <li>NGINX: Responsible for acting as a reverse proxy to distribute CAPIF requests to the different services, controlling whether or not they are authorized to access them.</li> <li>REDIS: Used for internal communication of services.</li> <li>CAPIF MONGO DATABASE: CAPIF database, where all information related to CAPIF services such as invokers, registered providers or published services is stored.</li> <li>HELPER: Service that simplifies integration with third parties such as external management portals.</li> </ul>"},{"location":"architecture/#new-architecture","title":"New Architecture","text":"<p>You can check the details of all these changes in the conversation on the OCF wiki.</p>"},{"location":"releasenotes/","title":"Releasenotes","text":""},{"location":"releasenotes/#release-100","title":"Release 1.0.0","text":""},{"location":"releasenotes/#new-features","title":"New Features","text":""},{"location":"releasenotes/#registration-flow-improved","title":"Registration Flow improved","text":"<ul> <li>Eliminated access from CAPIF to the Register user database when onboarding is performed.</li> <li>Isolation between CCF and Register services, interaction now is only by HTTPS requested between Register, CCF and Vault.</li> <li>Eliminated the \"role\" in user creation.<ul> <li>Now a user can be an invoker or a provider at the same time</li> </ul> </li> <li>Administrator User:<ul> <li>New entity in charge of registering and managing users of the register service.</li> </ul> </li> <li>UUID to identify users.<ul> <li>When you create a user, a uuid is associated with it</li> <li>The uuid will be contained in the token requested by the user and will be used to relate invokers and providers with users.</li> </ul> </li> <li>Endpoints changed and created:<ul> <li>Administrator endpoints:<ul> <li>/createUser: /register endpoint changed to createUser. Used to register new users.</li> <li>/deleteUser: /remove endpoint changed to this. Used to delete users and all the entities they had created.</li> <li>/login: Allows administrator to log in to obtain the necessary tokens for their requests.</li> <li>/refresh: Retrieve new access token token.</li> <li>/getUsers: Returns the list with all registered users.</li> </ul> </li> <li>Customer User:<ul> <li>/getauth now also returns the urls needed to use CAPIF, used by customer.</li> </ul> </li> </ul> </li> <li> <p>Security improvements:</p> <ul> <li>/login uses basic auth with administrator credentials.</li> <li>/getauth uses basic auth with customer user credentials.</li> <li>Other requests use the administrator access token obtained from login.</li> </ul> </li> <li> <p>Current fields on user creation by administrator:</p> </li> </ul> <pre><code>required_fields = {\n    \"username\": str,\n    \"password\": str,\n    \"enterprise\": str,\n    \"country\": str,\n    \"email\": str,\n    \"purpose\": str\n}\n\noptional_fields = {\n    \"phone_number\": str,\n    \"company_web\": str,\n    \"description\": str\n}\n</code></pre> <ul> <li>Test plan has been updated with the new register flow. Please check OCF Registration Flow</li> <li>Video with explanation and demonstration of new register flow New Registration Demo</li> </ul>"},{"location":"releasenotes/#new-opencapif-architecture","title":"New OpenCAPIF architecture","text":"<ul> <li>New arquitecture with separated namespaces for Vault, CCF and Register components. Communication between them now are only allowed by using REST APIs.</li> <li> <p>New helper service inside CCF, it will simplify integration with third parties like external management portals.</p> </li> <li> <p>Helper endpoints:</p> <ul> <li>/getInvokers : Get the list of invokers from CAPIF</li> <li>/getProviders: Get the list of providers from CAPIF</li> <li>/getServices : Get the list of services published in CAPIF</li> <li>/getSecurityContext : Get the list of security contexts from CAPIF</li> <li>/getEvents : Get the list of events subscriptions from CAPIF</li> <li>/deleteEntities: Removes all entities registered by a user from the register</li> </ul> </li> <li> <p>Security in the helper</p> <ul> <li>To make requests to the helper you will need a superadmin certificate and password.</li> </ul> </li> </ul>"},{"location":"releasenotes/#events-api-upgrade","title":"Events API Upgrade","text":"<ul> <li>The event management at CCF is improved, EventNotification include Event Details with required information.</li> <li>Events updated:<ul> <li>SERVICE_API_AVAILABLE and SERVICE_API_UNAVAILABLE with apiIds</li> <li>SERVICE_API_UPDATE with serviceAPIDescriptions</li> <li>API_INVOKER_ONBOARDED, API_INVOKER_UPDATED, API_INVOKER_OFFBOARDED with apiInvokerIds.</li> </ul> </li> <li>Events Included:<ul> <li>SERVICE_API_INVOCATION_SUCCESS and SERVICE_API_INVOCATION_FAILURE with invocationLogs</li> </ul> </li> <li>Test plan include 7 new tests in order to check new events implemented and scenarios of each notification implemented, with a complete check of Event Notification.</li> <li>Test plan documentation includes the new event tests OCF Event test plan documentation.</li> </ul>"},{"location":"releasenotes/#inital-implementation-of-cicd","title":"Inital implementation of CI/CD","text":"<ul> <li>The inital implementation of CI/CD on gitlab was performed.</li> <li>Detailed information in the CICD Wiki.</li> <li>Implement initial CI/CD:<ul> <li>Description of the CI process.<ul> <li>In CI phase, created design, jobs and security checks when a branch is pushed.</li> <li>The CI has jobs as:<ul> <li>Linting code, unit test (if needed),</li> <li>Build and push artifacts (images) in Git OCI register</li> <li>Security checks,</li> <li>SCA, CVS, SAST</li> <li>The vulnerabilities are exposed in Merge Request panel to be solved.</li> </ul> </li> </ul> </li> <li>Description of the CD process:<ul> <li>Defined the environments to OCF.<ul> <li>Production env.</li> <li>Pre-production env.</li> <li>Validation env.</li> <li>Dev-1, dev-2\u2026 envs (ephemeral)</li> </ul> </li> <li>Defined the naming convention to OCF releases<ul> <li>Tag in prod: v0.0.1-release</li> <li>Tag non-prod: v0.0.1-rc</li> <li>Other tags: v0.0.1-test, v0.0.1-smt</li> </ul> </li> <li>Defined the jobs of CD<ul> <li>CD ensures the deployment in multiple envs. Therefore, the CD pipeline has deploy-ocf, delete-ocf (if needed) jobs</li> </ul> </li> </ul> </li> <li>ETSI HIVE Labs:<ul> <li>Designed, created and the Kuberntes OCF cluster is running to support OCFs deployments.</li> <li>Iterating with ETSI HIVE\u2019s support to solve computing issues.<ul> <li>CPU compatibilities with OCF services (MongoDB): Fixed</li> </ul> </li> </ul> </li> </ul> </li> </ul>"},{"location":"releasenotes/#documentation","title":"Documentation","text":""},{"location":"releasenotes/#improvements-on-documentation","title":"Improvements on documentation","text":"<ul> <li>Documentation stored in OCF Documentation Repository</li> <li>Continuous Integration included at repository for web documentation:<ul> <li>Develop version of documentation is automatically generated on each merge to develop branch.</li> <li>Tagged version from main create documentation with related tag as version.</li> </ul> </li> </ul>"},{"location":"releasenotes/#technical-debt-solved","title":"Technical Debt Solved","text":""},{"location":"releasenotes/#improved-testing-with-robot-in-order-to-cover","title":"Improved Testing with Robot in order to cover","text":"<ul> <li>Support of new Register flows.</li> <li>Allow different URLs for register, ccf and vault services.</li> <li>New Variables included to manage new architecture under test.</li> <li>Mock server developed to add the functionality of write tests involving notification from Service Under Test.</li> <li>Docker image improved generation and libraries upgraded to Robot Framework 7.</li> </ul>"},{"location":"releasenotes/#improved-security-on-db","title":"Improved security on DB","text":"<ul> <li>Credentials requested to access mongo databases.</li> <li>Credentials requested also by mongo-express.</li> </ul>"},{"location":"releasenotes/#scripts-upgraded","title":"Scripts upgraded","text":"<ul> <li>Docker compose version 2 used on them.</li> <li>New cleaning script developed.</li> <li>Scripts upgraded:<ul> <li>check_services_are_running.sh: Checks if all essential services (Vault, CCF and Register) are running.</li> <li>clean_capif_docker_services.sh: Shutdowns and removes all services essential services.</li> <li>clean_capif_temporary_files.sh: Removes temporaly files from local repository. </li> <li>run.sh: Launch Essential services locally using docker compose, also monitoring can be launched.</li> <li>run_capif_tests.sh: Launch Robot Framwork Tests.</li> <li>show_logs.sh: Show locally logs of Services running.</li> <li>run_mock_server.sh: Launch mock server locally on all interfaces. This axiliary server is only used by tagged mockserver tests on Robot Framework.</li> <li>clean_mock_server.sh: Remove mock server local deployment.</li> <li>deploy.sh: This script simplify the way to download capif repository.</li> </ul> </li> </ul>"},{"location":"releasenotes/#codebase-improvements","title":"Codebase Improvements","text":"<ul> <li>Documentation is now on splitted repository OCF Documentation Repository</li> <li>Test plan was moved to OCF Documentation Repository</li> <li>Obsolote data is removed.</li> <li>Repository Reorganization: Enhanced structure and maintainability with a better directory layout and clearer module separation.</li> <li>Code Quality Enhancements: Refactored code and fixed known issues</li> </ul>"},{"location":"releasenotes/#migration-to-gunicorn","title":"Migration to GUNICORN","text":"<ul> <li>Include production server on each microservice: Release 0 use Flask developer server, now we use GUNICORN.</li> </ul>"},{"location":"releasenotes/#release-00","title":"Release 0.0","text":"<p>The APIs included in Release 0.0 are:</p> <ul> <li>JWT Authentication APIs</li> <li>CAPIF Invoker Management API</li> <li>CAPIF Publish API</li> <li>CAPIF Discover API</li> <li>CAPIF Security API</li> <li>CAPIF Events API</li> <li>CAPIF Provider Management API</li> </ul> <p>This Release also includes a Robot Test Suite for all those services and a Postman Test Suite for simple testing.</p>"},{"location":"deployment_guide/deployment_guide/","title":"1. Deployment Guide","text":"<p>This section walks you through the process of deploying TeraFlowSDN on top of a machine running MicroK8s Kubernetes platform. The guide includes the details on configuring and installing the machine, installing and  configuring MicroK8s, and deploying and reporting the status of the TeraFlowSDN  controller.</p>"},{"location":"deployment_guide/deployment_guide/#11-configure-your-machine","title":"1.1. Configure your Machine","text":"<p>In this section, we describe how to configure a machine (physical or virtual) to be used as the deployment, execution, and development environment for the ETSI TeraFlowSDN controller. Choose your preferred environment below and follow the instructions provided.</p> <p>NOTE: If you already have a remote physical server fitting the requirements specified in this section feel free to use it instead of deploying a local VM. Check 1.1.1. Physical Server for further details.</p> <p>Virtualization platforms tested are:</p> <ul> <li>Physical Server</li> <li>Oracle Virtual Box</li> <li>VMWare Fusion</li> <li>OpenStack</li> <li>Vagrant Box</li> </ul>"},{"location":"deployment_guide/deployment_guide/#111-physical-server","title":"1.1.1. Physical ServerServer SpecificationsClusterized DeploymentNetworkingOperating SystemUpgrade the Ubuntu distribution","text":"<p>This section describes how to configure a physical server for running ETSI TeraFlowSDN(TFS) controller.</p> <p>Minimum Server Specifications for development and basic deployment</p> <ul> <li>CPU: 4 cores</li> <li>RAM: 8 GB</li> <li>Disk: 60 GB</li> <li>1 GbE NIC</li> </ul> <p>Recommended Server Specifications for development and basic deployment</p> <ul> <li>CPU: 6 cores</li> <li>RAM: 12 GB</li> <li>Disk: 80 GB</li> <li>1 GbE NIC</li> </ul> <p>Server Specifications for best development and deployment experience</p> <ul> <li>CPU: 8 cores</li> <li>RAM: 32 GB</li> <li>Disk: 120 GB</li> <li>1 GbE NIC</li> </ul> <p>NOTE: the specifications listed above are provided as a reference. They depend also on the CPU clock frequency, the RAM memory, the disk technology and speed, etc.</p> <p>For development purposes, it is recommended to run the VSCode IDE (or the IDE of your choice) in a more powerful server, for instance, the recommended server specifications for development and basic deployment.</p> <p>Given that TeraFlowSDN follows a micro-services architecture, for the deployment, it might be better to use many clusterized servers with many slower cores than a single server with few highly performant cores.</p> <p>You might consider creating a cluster of machines each featuring, at least, the minimum server specifications. That solution brings you scalability in the future.</p> <p>No explicit indications are given in terms of networking besides that servers need access to the Internet for downloading dependencies, binaries, and packages while building and deploying the TeraFlowSDN components.</p> <p>Besides that, the network requirements are essentially the same than that required for running a classical Kubernetes environment. To facilitate the deployment, we extensively use MicroK8s, thus the network requirements are, essentially, the same demanded by MicroK8s, especially, if you consider creating a Kubernetes cluster.</p> <p>As a reference, the other deployment solutions based on VMs assume the VM is connected to a virtual network configured with the IP range <code>10.0.2.0/24</code> and have the gateway at IP <code>10.0.2.1</code>. The VMs have the IP address <code>10.0.2.10</code>.</p> <p>The minimum required ports to be accessible are: - 22/SSH     : for management purposes - 80/HTTP    : for the TeraFlowSDN WebUI and Grafana dashboard - 8081/HTTPS : for the CockroachDB WebUI</p> <p>Other ports might be required if you consider to deploy addons such as Kubernetes observability, etc. The details on these ports are left appart given they might vary depending on the Kubernetes environment you use.</p> <p>The recommended Operating System for deploying TeraFlowSDN is Ubuntu Server 22.04 LTS or Ubuntu Server 20.04 LTS. Other version might work, but we have not tested them. We strongly recommend using Long Term Support (LTS) versions as they provide better stability.</p> <p>Below we provide some installation guidelines: - Installation Language: English - Autodetect your keyboard - If asked, select \"Ubuntu Server\" (do not select \"Ubuntu Server (minimized)\"). - Configure static network specifications (adapt them based on your particular setup):</p> Interface IPv4 Method Subnet Address Gateway Name servers Search domains enp0s3 Manual 10.0.2.0/24 10.0.2.10 10.0.2.1 8.8.8.8,8.8.4.4 <ul> <li>Leave proxy and mirror addresses as they are</li> <li>Let the installer self-upgrade (if asked).</li> <li>Use an entire disk for the installation</li> <li>Disable setup of the disk as LVM group</li> <li>Double check that NO swap space is allocated in the partition table. Kubernetes does not work properly with SWAP.</li> <li>Configure your user and system names:</li> <li>User name: <code>TeraFlowSDN</code></li> <li>Server's name: <code>tfs-vm</code></li> <li>Username: <code>tfs</code></li> <li>Password: <code>tfs123</code></li> <li>Install Open SSH Server</li> <li>Import SSH keys, if any.</li> <li>Featured Server Snaps</li> <li>Do not install featured server snaps. It will be done manually later to illustrate how to uninstall and reinstall them in case of trouble with.</li> <li>Let the system install and upgrade the packages.</li> <li>This operation might take some minutes depending on how old is the Optical Drive ISO image you use and your Internet connection speed.</li> <li>Restart the VM when the installation is completed.</li> </ul> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul>"},{"location":"deployment_guide/deployment_guide/#112-oracle-virtual-box","title":"1.1.2. Oracle Virtual BoxCreate a NAT Network in VirtualBoxCreate VM in VirtualBox:Install Ubuntu 22.04 LTS Operating System","text":"<p>This section describes how to configure a VM for running ETSI TeraFlowSDN(TFS) controller using Oracle VirtualBox. It has been tested with VirtualBox up to version 6.1.40 r154048.</p> <p>In \"Oracle VM VirtualBox Manager\", Menu \"File &gt; Preferences... &gt; Network\", create a NAT  network with the following specifications:</p> Name CIDR DHCP IPv6 TFS-NAT-Net 10.0.2.0/24 Disabled Disabled <p>Within the newly created \"TFS-NAT-Net\" NAT network, configure the following IPv4  forwarding rules:</p> Name Protocol Host IP Host Port Guest IP Guest Port SSH TCP 127.0.0.1 2200 10.0.2.10 22 HTTP TCP 127.0.0.1 8080 10.0.2.10 80 <p>Note: IP address 10.0.2.10 is the one that will be assigned to the VM.</p> <ul> <li>Name: TFS-VM</li> <li>Type/Version: Linux / Ubuntu (64-bit)</li> <li>CPU (*): 4 vCPUs @ 100% execution capacity</li> <li>RAM: 8 GB</li> <li>Disk: 60 GB, Virtual Disk Image (VDI), Dynamically allocated</li> <li>Optical Drive ISO Image: \"ubuntu-22.04.X-live-server-amd64.iso\"</li> <li>Download the latest Long Term Support (LTS) version of the Ubuntu Server image from Ubuntu 22.04 LTS, e.g., \"ubuntu-22.04.X-live-server-amd64.iso\".</li> <li>Note: use Ubuntu Server image instead of Ubuntu Desktop to create a lightweight VM.</li> <li>Network Adapter 1 (*): enabled, attached to NAT Network \"TFS-NAT-Net\"</li> <li>Minor adjustments (*):</li> <li>Audio: disabled</li> <li>Boot order: disable \"Floppy\"</li> </ul> <p>Note: (*) settings to be editing after the VM is created.</p> <p>In \"Oracle VM VirtualBox Manager\", start the VM in normal mode, and follow the  installation procedure. Below we provide some installation guidelines: - Installation Language: English - Autodetect your keyboard - If asked, select \"Ubuntu Server\" (do not select \"Ubuntu Server (minimized)\"). - Configure static network specifications:</p> Interface IPv4 Method Subnet Address Gateway Name servers Search domains enp0s3 Manual 10.0.2.0/24 10.0.2.10 10.0.2.1 8.8.8.8,8.8.4.4 <ul> <li>Leave proxy and mirror addresses as they are</li> <li>Let the installer self-upgrade (if asked).</li> <li>Use an entire disk for the installation</li> <li>Disable setup of the disk as LVM group</li> <li>Double check that NO swap space is allocated in the partition table. Kubernetes does not work properly with SWAP.</li> <li>Configure your user and system names:</li> <li>User name: TeraFlowSDN</li> <li>Server's name: tfs-vm</li> <li>Username: tfs</li> <li>Password: tfs123</li> <li>Install Open SSH Server</li> <li>Import SSH keys, if any.</li> <li>Featured Server Snaps</li> <li>Do not install featured server snaps. It will be done manually later to illustrate how to uninstall and reinstall them in case of trouble with.</li> <li>Let the system install and upgrade the packages.</li> <li>This operation might take some minutes depending on how old is the Optical Drive ISO image you use and your Internet connection speed.</li> <li>Restart the VM when the installation is completed.</li> </ul> <p>Upgrade the Ubuntu distribution</p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul> <p>Install VirtualBox Guest Additions On VirtualBox Manager, open the VM main screen. If you are running the VM in headless  mode, right click over the VM in the VirtualBox Manager window and click \"Show\". If a dialog informing about how to leave the interface of the VM is shown, confirm  pressing \"Switch\" button. The interface of the VM should appear.</p> <p>Click menu \"Device &gt; Insert Guest Additions CD image...\"</p> <p>On the VM terminal, type:</p> <pre><code>sudo apt-get install -y linux-headers-$(uname -r) build-essential dkms\n  # This command might take some minutes depending on your VM specs and your Internet access speed.\nsudo mount /dev/cdrom /mnt/\ncd /mnt/\nsudo ./VBoxLinuxAdditions.run\n  # This command might take some minutes depending on your VM specs.\nsudo reboot\n</code></pre>"},{"location":"deployment_guide/deployment_guide/#113-vmware-fusion","title":"1.1.3. VMWare FusionCreate VM in VMWare Fusion:Install Ubuntu 22.04.1 LTS Operating SystemUpgrade the Ubuntu distribution","text":"<p>This section describes how to configure a VM for running ETSI TeraFlowSDN(TFS) controller using VMWare Fusion. It has been tested with VMWare Fusion version 12 and 13.</p> <p>In \"VMWare Fusion\" manager, create a new network from the \"Settings/Network\" menu.</p> <ul> <li>Unlock to make changes</li> <li>Press the + icon and create a new network</li> <li>Change the name to TFS-NAT-Net</li> <li>Check \"Allow virtual machines on this network to connect to external network (NAT)\"</li> <li>Do not check \"Enable IPv6\"</li> <li>Add port forwarding for HTTP and SSH</li> <li>Uncheck \"Provide address on this network via DHCP\"</li> </ul> <p>Create a new VM an Ubuntu 22.04.1 ISO:</p> <ul> <li>Display Name: TeraFlowSDN</li> <li>Username: tfs</li> <li>Password: tfs123</li> </ul> <p>On the next screen press \"Customize Settings\", save the VM and in \"Settings\" change: - Change to use 4 CPUs - Change to access 8 GB of RAM - Change disk to size 60 GB - Change the network interface to use the previously created TFS-NAT-Net</p> <p>Run the VM to start the installation.</p> <p>The installation will be automatic, without any configuration required.</p> <ul> <li>Configure the guest IP, gateway and DNS:</li> </ul> <p>Using the Network Settings for the wired connection, set the IP to 10.0.2.10,   the mask to 255.255.255.0, the gateway to 10.0.2.2 and the DNS to 10.0.2.2.</p> <ul> <li>Disable and remove swap file:</li> </ul> <p>$ sudo swapoff -a   $ sudo rm /swapfile</p> <p>Then you can remove or comment the /swapfile entry in /etc/fstab</p> <ul> <li>Install Open SSH Server</li> <li> <p>Import SSH keys, if any.</p> </li> <li> <p>Restart the VM when the installation is completed.</p> </li> </ul> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre>"},{"location":"deployment_guide/deployment_guide/#114-openstack","title":"1.1.4. OpenStackCreate a Security Group in OpenStack <p> In OpenStack, go to Project - Network - Security Groups - Create Security Group with name TFS</p> <p>Add the following rules:</p>    Direction Ether Type IP Protocol Port Range Remote IP Prefix     Ingress IPv4 TCP 22 (SSH) 0.0.0.0/0   Ingress IPv4 TCP 2200 0.0.0.0/0   Ingress IPv4 TCP 8080 0.0.0.0/0   Ingress IPv4 TCP 80 0.0.0.0/0   Egress IPv4 Any Any 0.0.0.0/0   Egress IPv6 Any Any ::/0    <p>Note: The IP address will be assigned depending on the network you have configured inside OpenStack. This IP will have to be modified in TeraFlow configuration files which by default use IP 10.0.2.10</p> Create a flavour <p></p> <p>From dashboard (Horizon)</p> <p>Go to Admin - Compute - Flavors and press Create Flavor</p> <ul> <li>Name: TFS</li> <li>VCPUs: 4</li> <li>RAM (MB): 8192</li> <li>Root Disk (GB): 60</li> </ul> <p>From CLI</p> <pre><code> openstack flavor create TFS --id auto --ram 8192 --disk 60 --vcpus 8\n</code></pre> Create an instance in OpenStack: <p></p> <ul> <li>Instance name: TFS-VM</li> <li>Origin: [Ubuntu-22.04 cloud image] (https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img)</li> <li>Create new volume: No</li> <li>Flavor: TFS</li> <li>Networks: extnet </li> <li>Security Groups: TFS</li> <li>Configuration: Include the following cloud-config</li> </ul> <pre><code>#cloud-config\n# Modifies the password for the VM instance\nusername: ubuntu\npassword: &lt;your-password&gt;\nchpasswd: { expire: False }\nssh_pwauth: True\n</code></pre> Upgrade the Ubuntu distribution <p></p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul>","text":"<p>This section describes how to configure a VM for running ETSI TeraFlowSDN(TFS) controller using OpenStack. It has been tested with OpenStack Kolla up to Yoga version. </p>"},{"location":"deployment_guide/deployment_guide/#115-vagrant-box","title":"1.1.5. Vagrant Box <p>This section describes how to create a Vagrant Box, using the base virtual machine configured in Oracle Virtual Box.</p> Virtual Machine specifications <p> Most of the specifications can be as specified in the Oracle Virtual Box page, however, there are a few particularities to Vagrant that must be accommodated, such as:</p> <ul> <li>Virtual Hard Disk</li> <li>Size: 60GB (at least)</li> <li>Type: VMDK</li> </ul> <p></p> <p>Also, before initiating the VM and installing the OS, we'll need to:</p> <ul> <li>Disable Floppy in the 'Boot Order'</li> <li>Disable audio</li> <li>Disable USB</li> <li>Ensure Network Adapter 1 is set to NAT</li> </ul> Network configurations <p> At Network Adapt 1, the following port-forwarding rule must be set.</p>    Name Protocol Host IP Host Port Guest IP Guest Port     SSH TCP  2222  22    <p></p> Installing the OS <p></p> <p>For a Vagrant Box, it is generally suggested that the ISO's server version is used, as it is intended to be used via SSH, and any web GUI is expected to be forwarded to the host.</p> <p></p> <p></p> <p></p> <p>Make sure the disk is not configured as an LVM group!</p> <p></p> Vagrant ser <p> Vagrant expects by default, that in the box's OS exists the user <code>vagrant</code> with the password also being <code>vagrant</code>.</p> <p></p> SSH <p></p> <p>Vagrant uses SSH to connect to the boxes, so installing it now will save the hassle of doing it later.</p> <p></p> Features server snaps <p></p> <p>Do not install featured server snaps. It will be done manually later to illustrate how to uninstall and reinstall them in case of trouble with.</p> Updates <p></p> <p>Let the system install and upgrade the packages. This operation might take some minutes depending on how old is the Optical Drive ISO image you use and your Internet connection speed.</p> Upgrade the Ubuntu distribution <p></p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> <ul> <li>If asked to restart services, restart the default ones proposed.</li> <li>Restart the VM when the installation is completed.</li> </ul> Install VirtualBox Guest Additions <p> On VirtualBox Manager, open the VM main screen. If you are running the VM in headless  mode, right-click over the VM in the VirtualBox Manager window, and click \"Show\". If a dialog informing about how to leave the interface of the VM is shown, confirm  by pressing the \"Switch\" button. The interface of the VM should appear.</p> <p>Click the menu \"Device &gt; Insert Guest Additions CD image...\"</p> <p>On the VM terminal, type:</p> <pre><code>sudo apt-get install -y linux-headers-$(uname -r) build-essential dkms\n  # This command might take some minutes depending on your VM specs and your Internet access speed.\nsudo mount /dev/cdrom /mnt/\ncd /mnt/\nsudo ./VBoxLinuxAdditions.run\n  # This command might take some minutes depending on your VM specs.\nsudo reboot\n</code></pre> ETSI TFS Installation <p> After this, proceed to 1.2. Install Microk8s, after which, return to this wiki to finish the Vagrant Box creation.</p> Box configuration and creation <p> Make sure the ETSI TFS controller is correctly configured. You will not be able to change it after!</p> <p>It is advisable to do the next configurations from a host's terminal, via a SSH connection.</p> <pre><code>ssh -p 2222 vagrant@127.0.0.1\n</code></pre> Set root password <p> Set the root password to <code>vagrant</code>.</p> <pre><code>sudo passwd root\n</code></pre> Set the superuser <p> Set up the Vagrant user so that it\u2019s able to use sudo without being prompted for a password. Anything in the <code>/etc/sudoers.d/*</code> directory is included in the sudoers privileges when created by the root user. Create a new sudo file.</p> <pre><code>sudo visudo -f /etc/sudoers.d/vagrant\n</code></pre> <p>and add the following lines</p> <pre><code># add vagrant user\nvagrant ALL=(ALL) NOPASSWD:ALL\n</code></pre> <p>You can now test that it works by running a simple command.</p> <pre><code>sudo pwd\n</code></pre> <p>Issuing this command should result in an immediate response without a request for a password.</p> Install the Vagrant key <p> Vagrant uses a default set of SSH keys for you to directly connect to boxes via the CLI command <code>vagrant ssh</code>, after which it creates a new set of SSH keys for your new box. Because of this, we need to load the default key to be able to access the box after created.</p> <pre><code>chmod 0700 /home/vagrant/.ssh\nwget --no-check-certificate https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub -O /home/vagrant/.ssh/authorized_keys\nchmod 0600 /home/vagrant/.ssh/authorized_keys\nchown -R vagrant /home/vagrant/.ssh\n</code></pre> Configure the OpenSSH Server <p> Edit the <code>/etc/ssh/sshd_config</code> file:</p> <pre><code>sudo vim /etc/ssh/sshd_config\n</code></pre> <p>And uncomment the following line:</p> <pre><code>AuthorizedKeysFile %h/.ssh/authorized_keys\n</code></pre> <p>Then restart SSH.</p> <pre><code>sudo service ssh restart\n</code></pre> Package the box <p> Before you package the box, if you intend to make your box public, it is best to clean your bash history with:</p> <pre><code>history -c\n</code></pre> <p>Exit the SSH connection, and at you're host machine, package the VM:</p> <pre><code>vagrant package --base teraflowsdncontroller --output teraflowsdncontroller.box\n</code></pre> Test run the box <p> Add the base box to you local Vagrant box list:</p> <pre><code>vagrant box add --name teraflowsdncontroller ./teraflowsdncontroller.box\n</code></pre> <p>Now you should try to run it, for that you'll need to create a Vagrantfile. For a simple run, this is the minimal required code for this box:</p> <pre><code># -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n  config.vm.box = \"teraflowsdncontroller\"\n  config.vm.box_version = \"1.1.0\"\n  config.vm.network :forwarded_port, host: 8080 ,guest: 80\nend\n</code></pre> <p>Now you'll be able to spin up the virtual machine by issuing the command:</p> <pre><code>vagrant up\n</code></pre> <p>And connect to the machine using:</p> <pre><code>vagrant ssh\n</code></pre> Pre-configured boxes <p> If you do not wish to create your own Vagrant Box, you can use one of the existing ones created by TFS contributors. - davidjosearaujo/teraflowsdncontroller - ... </p> <p>To use them, you simply have to create a Vagrantfile and run <code>vagrant up controller</code> in the same directory. The following example Vagrantfile already allows you to do just that, with the bonus of exposing the multiple management GUIs to your <code>localhost</code>.</p> <pre><code>Vagrant.configure(\"2\") do |config|\n\n  config.vm.define \"controller\" do |controller|\n    controller.vm.box = \"davidjosearaujo/teraflowsdncontroller\"\n    controller.vm.network \"forwarded_port\", guest: 80, host: 8080     # WebUI\n    controller.vm.network \"forwarded_port\", guest: 8084, host: 50750  # Linkerd Viz Dashboard\n    controller.vm.network \"forwarded_port\", guest: 8081, host: 8081   # CockroachDB Dashboard\n    controller.vm.network \"forwarded_port\", guest: 8222, host: 8222   # NATS Dashboard\n    controller.vm.network \"forwarded_port\", guest: 9000, host: 9000   # QuestDB Dashboard\n    controller.vm.network \"forwarded_port\", guest: 9090, host: 9090   # Prometheus Dashboard\n\n    # Setup Linkerd Viz reverse proxy\n    ## Copy config file\n    controller.vm.provision \"file\" do |f|\n      f.source = \"./reverse-proxy-linkerdviz.sh\"\n      f.destination = \"./reverse-proxy-linkerdviz.sh\"\n    end\n    ## Execute configuration file\n    controller.vm.provision \"shell\" do |s|\n      s.inline = \"chmod +x ./reverse-proxy-linkerdviz.sh &amp;&amp; ./reverse-proxy-linkerdviz.sh\"\n    end\n\n    # Update controller source code to the desired branch\n    if ENV['BRANCH'] != nil\n      controller.vm.provision \"shell\" do |s|\n        s.inline = \"cd ./tfs-ctrl &amp;&amp; git pull &amp;&amp; git switch \" + ENV['BRANCH']\n      end\n    end\n\n  end\nend\n</code></pre> <p>This Vagrantfile also allows for optional repository updates on startup by running the command with a specified environment variable <code>BRANCH</code></p> <pre><code>BRANCH=develop vagrant up controller\n</code></pre> Linkerd DNS rebinding bypass <p> Because of Linkerd's security measures against DNS rebinding, a reverse proxy, that modifies the request's header <code>Host</code> field, is needed to expose the GUI to the host. The previous Vagrantfile already deploys such configurations, for that, all you need to do is create the <code>reverse-proxy-linkerdviz.sh</code> file in the same directory. The content of this file is displayed below.</p> <pre><code># Install NGINX\nsudo apt update &amp;&amp; sudo apt install nginx -y\n\n# NGINX reverse proxy configuration\necho 'server {\n    listen 8084;\n\n    location / {\n        proxy_pass http://127.0.0.1:50750;\n        proxy_set_header Host localhost;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}' &gt; /home/vagrant/expose-linkerd\n\n# Create symlink of the NGINX configuration file\nsudo ln -s /home/vagrant/expose-linkerd /etc/nginx/sites-enabled/\n\n# Commit the reverse proxy configurations\nsudo systemctl restart nginx\n\n# Enable start on login\necho \"linkerd viz dashboard &amp;\" &gt;&gt; .profile\n\n# Start dashboard\nlinkerd viz dashboard &amp;\n\necho \"Linkerd Viz dashboard running!\"\n</code></pre>","text":""},{"location":"deployment_guide/deployment_guide/#12-install-microk8s","title":"1.2. Install MicroK8s","text":"<p>This section describes how to deploy the MicroK8s Kubernetes platform and configure it to be used with ETSI TeraFlowSDN controller. Besides, Docker is installed to build docker images for the ETSI TeraFlowSDN controller.</p> <p>The steps described in this section might take some minutes depending on your internet connection speed and the resources assigned to your VM, or the specifications of your physical server.</p> <p>To facilitate work, these steps are easier to be executed through an SSH connection, for instance using tools like PuTTY or MobaXterm.</p> Upgrade the Ubuntu distribution <p> Skip this step if you already did it during the creation of the VM.</p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> Install prerequisites <p></p> <pre><code>sudo apt-get install -y ca-certificates curl gnupg lsb-release snapd jq\n</code></pre> Install Docker CE <p> Install Docker CE and Docker BuildX plugin</p> <pre><code>sudo apt-get install -y docker.io docker-buildx\n</code></pre> <p>NOTE: Starting from Docker v23, Build architecture has been updated and <code>docker build</code> command entered into deprecation process in favor of the new <code>docker buildx build</code> command. Package <code>docker-buildx</code> provides the new <code>docker buildx build</code> command.</p> <p>Add key \"insecure-registries\" with the private repository to the daemon configuration. It is done in two commands since sometimes read from and write to same file might cause trouble.</p> <pre><code>if [ -s /etc/docker/daemon.json ]; then cat /etc/docker/daemon.json; else echo '{}'; fi \\\n    | jq 'if has(\"insecure-registries\") then . else .+ {\"insecure-registries\": []} end' -- \\\n    | jq '.\"insecure-registries\" |= (.+ [\"localhost:32000\"] | unique)' -- \\\n    | tee tmp.daemon.json\nsudo mv tmp.daemon.json /etc/docker/daemon.json\nsudo chown root:root /etc/docker/daemon.json\nsudo chmod 600 /etc/docker/daemon.json\n</code></pre> <p>Restart the Docker daemon</p> <pre><code>sudo systemctl restart docker\n</code></pre> Install MicroK8s <p></p> <p>Important: Some TeraFlowSDN dependencies need to be executed on top of MicroK8s/Kubernetes v1.24. It is not guaranteed (by now) to run on newer versions.</p> <pre><code># Install MicroK8s\nsudo snap install microk8s --classic --channel=1.24/stable\n\n# Create alias for command \"microk8s.kubectl\" to be usable as \"kubectl\"\nsudo snap alias microk8s.kubectl kubectl\n</code></pre> <p>It is important to make sure that <code>ufw</code> will not interfere with the internal pod-to-pod and pod-to-Internet traffic. To do so, first check the status. If <code>ufw</code> is active, use the following command to enable the communication.</p> <pre><code>\n# Verify status of ufw firewall\nsudo ufw status\n\n# If ufw is active, install following rules to enable access pod-to-pod and pod-to-internet\nsudo ufw allow in on cni0 &amp;&amp; sudo ufw allow out on cni0\nsudo ufw default allow routed\n</code></pre> <p>NOTE: MicroK8s can be used to compose a Highly Available Kubernetes cluster enabling you to construct an environment combining the CPU, RAM and storage resources of multiple machines. If you are interested in this procedure, review the official instructions in How to build a highly available Kubernetes cluster with MicroK8s, in particular, the step Create a MicroK8s multi-node cluster.</p> <p>References:</p> <ul> <li>The lightweight Kubernetes &gt; Install MicroK8s</li> <li>Install a local Kubernetes with MicroK8s</li> <li>How to build a highly available Kubernetes cluster with MicroK8s</li> </ul> Add user to the docker and microk8s groups <p></p> <p>It is important that your user has the permission to run <code>docker</code> and <code>microk8s</code> in the  terminal. To allow this, you need to add your user to the <code>docker</code> and <code>microk8s</code> groups with the  following commands:</p> <pre><code>sudo usermod -a -G docker $USER\nsudo usermod -a -G microk8s $USER\nsudo chown -f -R $USER $HOME/.kube\nsudo reboot\n</code></pre> <p>In case that you get trouble executing the following commands, might due to the .kube folder is not automatically provisioned into your home folder, you may follow the steps below:</p> <pre><code>mkdir -p $HOME/.kube\nsudo chown -f -R $USER $HOME/.kube\nmicrok8s config &gt; $HOME/.kube/config\nsudo reboot\n</code></pre> Check status of Kubernetes and addons <p> To retrieve the status of Kubernetes once, run the following command:</p> <pre><code>microk8s.status --wait-ready\n</code></pre> <p>To retrieve the status of Kubernetes periodically (e.g., every 1 second), run the  following command:</p> <pre><code>watch -n 1 microk8s.status --wait-ready\n</code></pre> Check all resources in Kubernetes <p> To retrieve the status of the Kubernetes resources once, run the following command:</p> <pre><code>kubectl get all --all-namespaces\n</code></pre> <p>To retrieve the status of the Kubernetes resources periodically (e.g., every 1  second), run the following command:</p> <pre><code>watch -n 1 kubectl get all --all-namespaces\n</code></pre> Enable addons <p></p> <p>First, we need to enable the community plugins (maintained by third parties):</p> <pre><code>microk8s.enable community\n</code></pre> <p>The Addons to be enabled are:</p> <ul> <li><code>dns</code>: enables resolving the pods and services by name</li> <li><code>helm3</code>: required to install NATS</li> <li><code>hostpath-storage</code>: enables providing storage for the pods (required by <code>registry</code>)</li> <li><code>ingress</code>: deploys an ingress controller to expose the microservices outside Kubernetes</li> <li><code>registry</code>: deploys a private registry for the TFS controller images</li> <li><code>linkerd</code>: deploys the linkerd service mesh used for load balancing among replicas</li> <li><code>prometheus</code>: set of tools that enable TFS observability through per-component instrumentation</li> <li><code>metrics-server</code>: deploys the Kubernetes metrics server for API access to service metrics</li> </ul> <pre><code>microk8s.enable dns helm3 hostpath-storage ingress registry prometheus metrics-server linkerd\n</code></pre> <p>Important: Enabling some of the addons might take few minutes. Do not proceed with next steps until the addons are ready. Otherwise, the deployment might fail. To confirm everything is up and running:</p> <ol> <li>Periodically    Check the status of Kubernetes    until you see the addons [dns, ha-cluster, helm3, hostpath-storage, ingress, linkerd, metrics-server, prometheus, registry, storage] in the enabled block.</li> <li>Periodically    Check Kubernetes resources    until all pods are Ready and Running.</li> <li>If it takes too long for the Pods to be ready, we observed that rebooting the machine may help.</li> </ol> <p>Then, create aliases to make the commands easier to access:</p> <pre><code>sudo snap alias microk8s.helm3 helm3\nsudo snap alias microk8s.linkerd linkerd\n</code></pre> <p>To validate that <code>linkerd</code> is working correctly, run:</p> <pre><code>linkerd check\n</code></pre> <p>To validate that the <code>metrics-server</code> is working correctly, run:</p> <pre><code>kubectl top pods --all-namespaces\n</code></pre> <p>and you should see a screen similar to the <code>top</code> command in Linux, showing the columns namespace, pod name, CPU (cores), and MEMORY (bytes).</p> <p>In case pods are not starting, check information from pods logs. For example, linkerd is sensitive for proper /etc/resolv.conf syntax.</p> <pre><code>kubectl logs &lt;podname&gt; --namespace &lt;namespace&gt;\n</code></pre> <p>If the command shows an error message, also restarting the machine might help.</p> Stop, Restart, and Redeploy <p> Find below some additional commands you might need while you work with MicroK8s:</p> <pre><code>microk8s.stop  # stop MicroK8s cluster (for instance, before power off your computer)\nmicrok8s.start # start MicroK8s cluster\nmicrok8s.reset # reset infrastructure to a clean state\n</code></pre> <p>If the following commands does not work to recover the MicroK8s cluster, you can redeploy it.</p> <p>If you want to keep MicroK8s configuration, use:</p> <pre><code>sudo snap remove microk8s\n</code></pre> <p>If you need to completely drop MicroK8s and its complete configuration, use:</p> <pre><code>sudo snap remove microk8s --purge\nsudo apt-get remove --purge docker.io docker-buildx\n</code></pre> <p>IMPORTANT: After uninstalling MicroK8s, it is convenient to reboot the computer (the VM if you work on a VM, or the physical computer if you use a physical computer). Otherwise, there are system configurations that are not correctly cleaned. Especially in what port forwarding and firewall rules matters.</p> <p>After the reboot, redeploy as it is described in this section.</p>"},{"location":"deployment_guide/deployment_guide/#13-deploy-teraflowsdn","title":"1.3. Deploy TeraFlowSDN","text":"<p>This section describes how to deploy TeraFlowSDN controller on top of MicroK8s using the environment configured in the previous sections.</p> Install prerequisites <p></p> <pre><code>sudo apt-get install -y git curl jq\n</code></pre> Clone the Git repository of the TeraFlowSDN controller <p> Clone from ETSI-hosted GitLab code repository:</p> <pre><code>mkdir ~/tfs-ctrl\ngit clone https://labs.etsi.org/rep/tfs/controller.git ~/tfs-ctrl\n</code></pre> <p>Important: The original H2020-TeraFlow project hosted on GitLab.com has been  archieved and will not receive further contributions/updates. Please, clone from ETSI-hosted GitLab code repository.</p> Checkout the appropriate Git branch <p> TeraFlowSDN controller versions can be found in the appropriate release tags and/or branches as described in Home &gt; Versions.</p> <p>By default the branch master is checked out and points to the latest stable version of the TeraFlowSDN controller, while branch develop contains the latest developments and contributions under test and validation.</p> <p>To switch to the appropriate branch run the following command, changing <code>develop</code> by the name of the branch you want to deploy:</p> <pre><code>cd ~/tfs-ctrl\ngit checkout develop\n</code></pre> Prepare a deployment script with the deployment settings <p> Create a new deployment script, e.g., <code>my_deploy.sh</code>, adding the appropriate settings as  follows. This section provides just an overview of the available settings. An example <code>my_deploy.sh</code> script is provided in the root folder of the project for your convenience with full description of all the settings.</p> <p>Note: The example <code>my_deploy.sh</code> script provides reasonable settings for deploying a functional and complete enough TeraFlowSDN controller, and a brief description of their meaning. To see extended descriptions, check scripts in the <code>deploy</code> folder.</p> <pre><code>cd ~/tfs-ctrl\ntee my_deploy.sh &gt;/dev/null &lt;&lt; EOF\n# ----- TeraFlowSDN ------------------------------------------------------------\nexport TFS_REGISTRY_IMAGES=\"http://localhost:32000/tfs/\"\nexport TFS_COMPONENTS=\"context device ztp monitoring pathcomp service slice nbi webui load_generator\"\nexport TFS_IMAGE_TAG=\"dev\"\nexport TFS_K8S_NAMESPACE=\"tfs\"\nexport TFS_EXTRA_MANIFESTS=\"manifests/nginx_ingress_http.yaml\"\nexport TFS_GRAFANA_PASSWORD=\"admin123+\"\nexport TFS_SKIP_BUILD=\"\"\n\n# ----- CockroachDB ------------------------------------------------------------\nexport CRDB_NAMESPACE=\"crdb\"\nexport CRDB_EXT_PORT_SQL=\"26257\"\nexport CRDB_EXT_PORT_HTTP=\"8081\"\nexport CRDB_USERNAME=\"tfs\"\nexport CRDB_PASSWORD=\"tfs123\"\nexport CRDB_DATABASE=\"tfs\"\nexport CRDB_DEPLOY_MODE=\"single\"\nexport CRDB_DROP_DATABASE_IF_EXISTS=\"YES\"\nexport CRDB_REDEPLOY=\"\"\n\n# ----- NATS -------------------------------------------------------------------\nexport NATS_NAMESPACE=\"nats\"\nexport NATS_EXT_PORT_CLIENT=\"4222\"\nexport NATS_EXT_PORT_HTTP=\"8222\"\nexport NATS_REDEPLOY=\"\"\n\n# ----- QuestDB ----------------------------------------------------------------\nexport QDB_NAMESPACE=\"qdb\"\nexport QDB_EXT_PORT_SQL=\"8812\"\nexport QDB_EXT_PORT_ILP=\"9009\"\nexport QDB_EXT_PORT_HTTP=\"9000\"\nexport QDB_USERNAME=\"admin\"\nexport QDB_PASSWORD=\"quest\"\nexport QDB_TABLE_MONITORING_KPIS=\"tfs_monitoring_kpis\"\nexport QDB_TABLE_SLICE_GROUPS=\"tfs_slice_groups\"\nexport QDB_DROP_TABLES_IF_EXIST=\"YES\"\nexport QDB_REDEPLOY=\"\"\n\nEOF\n</code></pre> <p>The settings are organized in 4 sections: - Section <code>TeraFlowSDN</code>:   - <code>TFS_REGISTRY_IMAGE</code> enables to specify the private Docker registry to be used, by default, we assume to use the Docker respository enabled in MicroK8s.   - <code>TFS_COMPONENTS</code> specifies the components their Docker image will be rebuilt, uploaded to the private Docker registry, and deployed in Kubernetes.   - <code>TFS_IMAGE_TAG</code> defines the tag to be used for Docker images being rebuilt and uploaded to the private Docker registry.   - <code>TFS_K8S_NAMESPACE</code> specifies the name of the Kubernetes namespace to be used for deploying the TFS components.   - <code>TFS_EXTRA_MANIFESTS</code> enables to provide additional manifests to be applied into the Kubernetes environment during the deployment. Typical use case is to deploy ingress controllers, service monitors for Prometheus, etc.   - <code>TFS_GRAFANA_PASSWORD</code> lets you specify the password you want to use for the <code>admin</code> user of the Grafana instance being deployed and linked to the Monitoring component.   - <code>TFS_SKIP_BUILD</code>, if set to <code>YES</code>, prevents rebuilding the Docker images. That means, the deploy script will redeploy existing Docker images without rebuilding/updating them.</p> <ul> <li>Section <code>CockroachDB</code>: enables to configure the deployment of the backend CockroachDB database.</li> <li> <p>Check example script <code>my_deploy.sh</code> for further details.</p> </li> <li> <p>Section <code>NATS</code>: enables to configure the deployment of the backend NATS message broker.</p> </li> <li> <p>Check example script <code>my_deploy.sh</code> for further details.</p> </li> <li> <p>Section <code>QuestDB</code>: enables to configure the deployment of the backend QuestDB timeseries database.</p> </li> <li>Check example script <code>my_deploy.sh</code> for further details.</li> </ul> Confirm that MicroK8s is running <p></p> <p>Run the following command:</p> <pre><code>microk8s status\n</code></pre> <p>If it is reported <code>microk8s is not running, try microk8s start</code>, run the following command to start MicroK8s:</p> <pre><code>microk8s start\n</code></pre> <p>Confirm everything is up and running:</p> <ol> <li>Periodically Check the status of Kubernetes until you see the addons [dns, ha-cluster, helm3, hostpath-storage, ingress, registry, storage] in the enabled block.</li> <li>Periodically Check Kubernetes resources until all pods are Ready and Running.</li> </ol> Deploy TFS controller <p> First, source the deployment settings defined in the previous section. This way, you do not need to specify the environment variables in each and every command you execute to operate the TFS controller. Be aware to re-source the file if you open new terminal sessions. Then, run the following command to deploy TeraFlowSDN controller on top of the MicroK8s Kubernetes platform.</p> <pre><code>cd ~/tfs-ctrl\nsource my_deploy.sh\n./deploy/all.sh\n</code></pre> <p>The script performs the following steps:</p> <ul> <li>Executes script <code>./deploy/crdb.sh</code> to automate deployment of CockroachDB database used by Context component.</li> <li>The script automatically checks if CockroachDB is already deployed.</li> <li>If there are settings instructing to drop the database and/or redeploy CockroachDB, it does the appropriate actions to honor them as defined in previous section.</li> <li>Executes script <code>./deploy/nats.sh</code> to automate deployment of NATS message broker used by Context component.</li> <li>The script automatically checks if NATS is already deployed.</li> <li>If there are settings instructing to redeploy the message broker, it does the appropriate actions to honor them as defined in previous section.</li> <li>Executes script <code>./deploy/qdb.sh</code> to automate deployment of QuestDB timeseries database used by Monitoring component.</li> <li>The script automatically checks if QuestDB is already deployed.</li> <li>If there are settings instructing to redeploy the timeseries database, it does the appropriate actions to honor them as defined in previous section.</li> <li>Executes script <code>./deploy/tfs.sh</code> to automate deployment of TeraFlowSDN.</li> <li>Creates the namespace defined in <code>TFS_K8S_NAMESPACE</code></li> <li>Creates secrets for CockroachDB, NATS, and QuestDB to be used by Context and Monitoring components.</li> <li>Builds the Docker images for the components defined in <code>TFS_COMPONENTS</code></li> <li>Tags the Docker images with the value of <code>TFS_IMAGE_TAG</code></li> <li>Pushes the Docker images to the repository defined in <code>TFS_REGISTRY_IMAGE</code></li> <li>Deploys the components defined in <code>TFS_COMPONENTS</code></li> <li>Creates the file <code>tfs_runtime_env_vars.sh</code> with the environment variables for the components defined in <code>TFS_COMPONENTS</code> defining their local host addresses and their port numbers.</li> <li>Applies extra manifests defined in <code>TFS_EXTRA_MANIFESTS</code> such as:<ul> <li>Creating an ingress controller listening at port 80 for HTTP connections to enable external access to the TeraFlowSDN WebUI, Grafana Dashboards, and Compute NBI interfaces.</li> <li>Deploying service monitors to enable monitoring the performance of the components, device drivers and service handlers.</li> </ul> </li> <li>Initialize and configure the Grafana dashboards (if Monitoring component is deployed)</li> <li>Report a summary of the deployment</li> <li>See Show Deployment and Logs</li> </ul>"},{"location":"deployment_guide/deployment_guide/#14-webui-and-grafana-dashboards","title":"1.4. WebUI and Grafana Dashboards","text":"<p>This section describes how to get access to the TeraFlowSDN controller WebUI and the monitoring Grafana dashboards.</p> Access the TeraFlowSDN WebUI <p> If you followed the installation steps based on MicroK8s, you got an ingress controller installed that exposes on TCP port 80.</p> <p>Besides, the ingress controller defines the following reverse proxy paths (on your local machine):</p> <ul> <li><code>http://127.0.0.1/webui</code>: points to the WebUI of TeraFlowSDN.</li> <li><code>http://127.0.0.1/grafana</code>: points to the Grafana dashboards.   This endpoint brings access to the monitoring dashboards of TeraFlowSDN.   The credentials for the <code>admin</code>user are those defined in the <code>my_deploy.sh</code> script, in the <code>TFS_GRAFANA_PASSWORD</code> variable.</li> <li><code>http://127.0.0.1/restconf</code>: points to the Compute component NBI based on RestCONF.    This endpoint enables connecting external software, such as ETSI OpenSourceMANO NFV Orchestrator, to TeraFlowSDN.</li> </ul> <p>Note: In the creation of the VM, a forward from host TCP port 8080 to VM's TCP port 80 is configured, so the WebUIs and REST APIs of TeraFlowSDN should be exposed on the endpoint <code>127.0.0.1:8080</code> of your local machine instead of <code>127.0.0.1:80</code>.</p>"},{"location":"deployment_guide/deployment_guide/#15-show-deployment-and-logs","title":"1.5. Show Deployment and Logs","text":"<p>This section presents some helper scripts to inspect the status of the deployment and  the logs of the components. These scripts are particularly helpful for troubleshooting during execution of  experiments, development, and debugging.</p> Report the deployment of the TFS controller <p></p> <p>The summary report given at the end of the Deploy TFS controller procedure can be generated manually at any time by running the following command. You can avoid sourcing <code>my_deploy.sh</code> if it has been already done.</p> <pre><code>cd ~/tfs-ctrl\nsource my_deploy.sh\n./deploy/show.sh\n</code></pre> <p>Use this script to validate that all the pods, deployments, replica sets, ingress  controller, etc. are ready and have the appropriate state, e.g., running for Pods, and  the services are deployed and have appropriate IP addresses and port numbers.</p> Report the log of a specific TFS controller component <p></p> <p>A number of scripts are pre-created in the <code>scripts</code> folder to facilitate the inspection  of the component logs. For instance, to dump the log of the Context component, run the following command. You can avoid sourcing <code>my_deploy.sh</code> if it has been already done.</p> <pre><code>source my_deploy.sh\n./scripts/show_logs_context.sh\n</code></pre>"},{"location":"development_guide/development_guide/","title":"2. Development Guide","text":""},{"location":"development_guide/development_guide/#21-configure-environment","title":"2.1. Configure Environment","text":""},{"location":"development_guide/development_guide/#211-python","title":"2.1.1. PythonUpgrade the Ubuntu distribution  <p>Skip this step if you already did it during the installation of your machine.</p> <pre><code>sudo apt-get update -y\nsudo apt-get dist-upgrade -y\n</code></pre> Install PyEnv dependencies <p></p> <pre><code>sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget \\\n    curl llvm git libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev\n</code></pre> Install PyEnv <p></p> <p>We recommend installing PyEnv through PyEnv Installer. Below you can find the instructions, but we refer you to the link for updated  instructions.</p> <pre><code>curl https://pyenv.run | bash\n# When finished, edit ~/.bash_profile // ~/.profile // ~/.bashrc as the installer proposes.\n# In general, it means to append the following lines to ~/.bashrc:\nexport PYENV_ROOT=\"$HOME/.pyenv\"\ncommand -v pyenv &gt;/dev/null || export PATH=\"$PYENV_ROOT/bin:$PATH\"\neval \"$(pyenv init -)\"\neval \"$(pyenv virtualenv-init -)\"\n</code></pre> <p>In case .bashrc is not linked properly to your profile, you may need to append the  following line into your local .profile file:</p> <pre><code># Open ~/.profile and append this line:\n+source \"$HOME\"/.bashrc\n</code></pre> Restart the machine <p> Restart the machine for all the changes to take effect.</p> <pre><code>sudo reboot\n</code></pre> Install Python 3.9 over PyEnv <p></p> <p>ETSI TeraFlowSDN uses Python 3.9 by default. You should install the latest stable update of Python 3.9, i.e., avoid \"-dev\" versions. To find the latest version available in PyEnv, you can run the following command:</p> <pre><code>pyenv install --list | grep \" 3.9\"\n</code></pre> <p>At the time of writing, this command will output the following list:</p> <pre><code>  3.9.0\n  3.9-dev\n  3.9.1\n  3.9.2\n  3.9.4\n  3.9.5\n  3.9.6\n  3.9.7\n  3.9.8\n  3.9.9\n  3.9.10\n  3.9.11\n  3.9.12\n  3.9.13\n  3.9.14 \n  3.9.15\n  3.9.16 ** always select the latest version **\n</code></pre> <p>Therefore, the latest stable version is Python 3.9.16. To install this version, you should run:</p> <pre><code>pyenv install 3.9.16\n    # This command might take some minutes depending on your Internet connection speed \n    # and the performance of your machine.\n</code></pre> Create the Virtual Environment for TeraFlowSDN <p> The following commands create a virtual environment named as <code>tfs</code> using Python 3.9 and  associate that environment with the current folder, i.e., <code>~/tfs-ctrl</code>. That way, when you are in that folder, the associated virtual environment will be used,  thus inheriting the Python interpreter, i.e., Python 3.9, and the Python packages  installed on it.</p> <pre><code>cd ~/tfs-ctrl\npyenv virtualenv 3.9.16 tfs\npyenv local 3.9.16/envs/tfs\n</code></pre> <p>After completing these commands, you should see in your prompt that now you're within  the virtual environment <code>3.9.16/envs/tfs</code> on folder <code>~/tfs-ctrl</code>:</p> <pre><code>(3.9.16/envs/tfs) tfs@tfs-vm:~/tfs-ctrl$\n</code></pre> <p>In case that the correct pyenv does not get automatically activated when you change to  the tfs-ctrl/ folder, then execute the following command:</p> <pre><code>cd ~/tfs-ctrl\npyenv activate 3.9.16/envs/tfs\n</code></pre> Install the basic Python packages within the virtual environment <p> From within the <code>3.9.16/envs/tfs</code> environment on folder <code>~/tfs-ctrl</code>, run the following  commands to install the basic Python packages required to work with TeraFlowSDN.</p> <pre><code>cd ~/tfs-ctrl\n./install_requirements.sh\n</code></pre> <p>Some dependencies require to re-load the session, so log-out and log-in again.</p> Generate the Python code from the gRPC Proto messages and services <p></p> <p>The components, e.g., microservices, of the TeraFlowSDN controller, in general, use a gRPC-based open API to interoperate. All the protocol definitions can be found in sub-folder <code>proto</code> within the root project folder. For additional details on gRPC, visit the official web-page gRPC.</p> <p>In order to interact with the components, (re-)generate the Python code from gRPC definitions running the following command:</p> <pre><code>cd ~/tfs-ctrl\nproto/generate_code_python.sh\n</code></pre>","text":"<p>This section describes how to configure the Python environment to run experiments and  develop code for the ETSI TeraFlowSDN controller. In particular, we use PyEnv to install the appropriate  version of Python and manage the virtual environments.</p>"},{"location":"development_guide/development_guide/#212-java-quarkus","title":"2.1.2. Java (Quarkus) <p>This section describe the steps needed to create a development environment for TFS components implemented in Java. Currently, ZTP and Policy components have been developed in Java (version 11) and use the Quarkus framework, which enables kubernetes-native development.</p> Install JDK <p> To begin, make sure that you have java installed and in the correct version</p> <pre><code>java --version\n</code></pre> <p>If you don't have java installed you will get an error like the following:</p> <pre><code>Command 'java' not found, but can be installed with:\n\nsudo apt install default-jre              # version 2:1.11-72build1, or\nsudo apt install openjdk-11-jre-headless  # version 11.0.14+9-0ubuntu2\nsudo apt install openjdk-17-jre-headless  # version 17.0.2+8-1\nsudo apt install openjdk-18-jre-headless  # version 18~36ea-1\nsudo apt install openjdk-8-jre-headless   # version 8u312-b07-0ubuntu1\n</code></pre> <p>In which case you should use the following command to install the correct version:</p> <pre><code>sudo apt install openjdk-11-jre-headless\n</code></pre> <p>Else you should get something like the following:</p> <pre><code>openjdk 11.0.18 2023-01-17\nOpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1)\nOpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1, mixed mode, sharing)\n</code></pre> Compiling and testing existing components <p> In the root directory of the existing Java components you will find an executable maven wrapper named <code>mvnw</code>. You could use this executable, which is already configured in pair with the components, instead of your local maven installation. So for example if you want to compile the project you would run the following:</p> <pre><code>./mvnw compile\n</code></pre> VS Code Quarkus plugin <p> In case you are using VS Code for development, we suggest to install the official Quarkus extension. The extension should be able to automatically find the current open project and integrate with the above <code>mvnw</code> maven wrapper, making it easier to control the maven lifecycle. Make sure that you open the specific component directory (i.e., <code>src/ztp</code> or <code>src/policy</code>) and not the general controller one (i.e., <code>src</code>.</p> New Java TFS component <p></p> <p>Sample Project</p> <p>If you want to create a new TFS component written in Java you could generate a new Quarkus project based on the following project:</p> <p>TFS Sample Quarkus Project</p> <p>In that way, you should have most of the libraries you would need to integrate with the rest of the TFS Components. Feel free however to add or remove libraries depending on your needs.</p> <p>Initial setup</p> <p>If you used the sample project above, you should have a project with a basic structure. However there are some steps that you should take before starting development.</p> <p>First make sure that you copy the protobuff files, that are found in the root directory of the TFS SDN controller, to the <code>new-component/src/main/proto</code> directory.</p> <p>Next you should create the following files:</p> <ul> <li><code>new-component/.gitlab-ci.yml</code></li> <li><code>new-component/Dockerfile</code></li> <li><code>new-component/src/resources/application.yaml</code></li> </ul> <p>We suggest to copy the respective files from existing components (Automation and Policy) and change them according to your needs.</p>","text":""},{"location":"development_guide/development_guide/#213-java-maven","title":"2.1.3. Java (Maven) <p>Page under construction</p>","text":""},{"location":"development_guide/development_guide/#214-rust","title":"2.1.4. Rust <p>Page under construction</p>","text":""},{"location":"development_guide/development_guide/#215-erlang","title":"2.1.5. Erlang <p>This section describes how to configure the Erlang environment to run experiments and develop code for the ETSI TeraFlowSDN controller.</p> <p>First we need to install Erlang. There is multiple way, for development we will be using ASDF, a tool that allows the installation of multiple version of Erlang at the same time, and switch from one version to the other at will.</p> <ul> <li>First, install any missing dependencies:</li> </ul> <pre><code>sudo apt install curl git autoconf libncurses-dev build-essential m4 libssl-dev \n</code></pre> <ul> <li>Download ASDF tool to the local account:</li> </ul> <pre><code>git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.2\n</code></pre> <ul> <li>Make ASDF activate on login by adding these lines at the end of the <code>~/.bashrc</code> file:</li> </ul> <pre><code>. $HOME/.asdf/asdf.sh\n. $HOME/.asdf/completions/asdf.bash\n</code></pre> <ul> <li>Logout and log back in to activate ASDF.</li> </ul> <p>ASDF supports multiple tools by installing there corresponding plugins.</p> <ul> <li>Install ASDF plugin for Erlang:</li> </ul> <pre><code>asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git\n</code></pre> <ul> <li>Install a version of Erlang:</li> </ul> <pre><code>asdf install erlang 24.3.4.2\n</code></pre> <ul> <li>Activate Erlang locally for TFS controller. This will create a local file called <code>.tool-versions</code> defining which version of the tools to use when running under the current directory:</li> </ul> <pre><code>cd tfs-ctrl/\nasdf local erlang 24.3.4.2\n</code></pre> <p>Erlang projects uses a build tool called rebar3. It is used to manager project dependenecies, compile a project and generate project releases.</p> <ul> <li>Install rebar3 localy from source:</li> </ul> <pre><code>cd ~\ngit clone https://github.com/erlang/rebar3.git\ncd rebar3\nasdf local erlang 24.3.4.2\n./bootstrap\n./rebar3 local install\n</code></pre> <ul> <li>Update <code>~/.bashrc</code> to use rebar3 by adding this line at the end:</li> </ul> <pre><code>export PATH=$HOME/.cache/rebar3/bin:$PATH\n</code></pre> <ul> <li>Logout and log back in.</li> </ul>","text":""},{"location":"development_guide/development_guide/#216-kotlin","title":"2.1.6. Kotlin <p>This section describes the steps needed to establish a development environment for TFS (TeraFlowSDN) components implemented in Kotlin. Currently, the <code>Gateway</code> component stands as the sole component developed in Kotlin.</p> Install Kotlin <p> To begin, make sure that you have kotlin installed and its current version:</p> <pre><code>kotlin -version\n</code></pre> <p>If you don't have kotlin installed you will get an error like the following:</p> <pre><code>Command 'kotlin' not found, but can be installed with:\nsudo snap install --classic kotlin\n</code></pre> <p>In which case you should use the following command to install the correct version:</p> <pre><code> sudo snap install --classic kotlin\n</code></pre> <p>Currently, the recommended version is 1.6.21, which uses Java Runtime Environment (JRE) version 11.</p> Compiling and testing existing components <p> To compile a Kotlin project using Gradle, similarly to using the Maven wrapper (mvnw) for Java projects, you can use the Gradle wrapper (gradlew) within the root directory of your Kotlin component, specifically the gateway directory.</p> <p>Navigate to the gateway directory within your Kotlin project. Ensure that it contains the gradlew script along with the gradle directory. Then, create a directory named <code>proto</code> and move all the files with extension <code>.proto</code> in this way:</p> <pre><code>mkdir proto\ncp ../../../proto/*.proto ./proto \n</code></pre> <p>For building the application, open a terminal or command prompt, navigate to the gateway directory, and run the following command:</p> <pre><code>./gradlew build\n</code></pre> <p>The following program runs the gateway application:</p> <pre><code>./gradlew runServer \n</code></pre> New Kotlin TFS component <p></p> <p>Sample Project</p> <p>If you want to create a new TFS component written in Kotlin you could generate a Kotlin project using <code>gradle</code>. The recommended version is 7.1. Follow the following Gradle guide for its installation. For building the prokect follow this link instead.</p> <p>From inside the new project directory, run the init task using the following command in a terminal: <code>gradle init</code>. </p> <p>The output will look like this:</p> <pre><code>$ gradle init\n\nSelect type of project to generate:\n  1: basic\n  2: application\n  3: library\n  4: Gradle plugin\nEnter selection (default: basic) [1..4] 2\n\nSelect implementation language:\n  1: C++\n  2: Groovy\n  3: Java\n  4: Kotlin\n  5: Scala\n  6: Swift\nEnter selection (default: Java) [1..6] 4\n\nSelect build script DSL:\n  1: Groovy\n  2: Kotlin\nEnter selection (default: Groovy) [1..2] 1\n\nProject name (default: demo):\nSource package (default: demo):\n\n\nBUILD SUCCESSFUL\n2 actionable tasks: 2 executed\n</code></pre> <p>Initial setup</p> <p>The <code>gradle init</code> command generates the new project. </p> <p>First, ensure the protobuf files are copied from the root directory of the TFS SDN controller. Run the following command in the directory of the new project:</p> <pre><code>mkdir proto \ncp TFS/project/root/path/proto/*.proto ./proto/\n</code></pre> <p>The file <code>build.gradle.ktl</code> is fundamental as it manages dependencies. Adjust it for adding external libraries.  </p> <p>Next you should create the following files:</p> <ol> <li><code>new-component/.gitlab-ci.yml</code></li> <li><code>new-component/Dockerfile</code></li> </ol> <p>We recommend leveraging the structures and configurations found in the files of existing components for inspiration.</p> <p>Docker Container This project operates with Docker containers. Ensure the production of the container version for your component. To generate the container version of the project, modify the 'new-component/Dockerfile.' Execute the following command from the project's root directory:</p> <pre><code>docker build -t new-image -f new-component/Dockerfile ./\n</code></pre>","text":""},{"location":"development_guide/development_guide/#22-configure-vscode","title":"2.2. Configure VScode","text":"Install VSCode and the required extensions <p>If not already done, install VSCode and the \"Remote SSH\" extension on your local machine, not in the VM.</p> <p>Note: \"Python\" extension is not required here. It will be installed later on the VSCode server running on the VM.</p> Configure the \"Remote SSH\" extension <p></p> <ul> <li>Go to left icon \"Remote Explorer\"</li> <li>Click the \"gear\" icon next to \"SSH TARGETS\" on top of \"Remote Explorer\" bar</li> <li>Choose to edit \"&lt;...&gt;/.ssh/config\" file (or equivalent)</li> <li>Add the following entry (assuming previous port forwarding configuration):</li> </ul> <pre><code>Host TFS-VM\n    HostName 127.0.0.1\n    Port 2200\n    ForwardX11 no\n    User tfs\n</code></pre> <ul> <li>Save the file</li> <li>An entry \"TFS-VM\" should appear on \"SSH TARGETS\".</li> </ul> Connect VSCode to the VM through \"Remote SSH\" extension <p></p> <ul> <li>Right-click on \"TFS-VM\"</li> <li>Select \"Connect to Host in Current Window\"</li> <li>Reply to the questions asked</li> <li>Platform of the remote host \"TFS-VM\": Linux</li> <li>\"TFS-VM\" has fingerprint \"\". Do you want to continue?: Continue <li>Type tfs user's password: tfs123</li> <li>You should be now connected to the TFS-VM.</li> <p>Note: if you get a connection error message, the reason might be due to wrong SSH server fingerprint. Edit file           \"&lt;...&gt;/.ssh/known_hosts\" on your local user account, check if there is a line starting with           \"[127.0.0.1]:2200\" (assuming previous port forwarding configuration), remove the entire line, save the file,           and retry connection.</p> Add SSH key to prevent typing the password every time <p> This step creates an SSH key in the VM and installs it on the VSCode to prevent having to type the password every time.</p> <ul> <li>In VSCode (connected to the VM), click menu \"Terminal &gt; New Terminal\"</li> <li>Run the following commands on the VM's terminal through VSCode</li> </ul> <pre><code>ssh-keygen -t rsa -b 4096 -f ~/.ssh/tfs-vm.key\n  # leave password empty\nssh-copy-id -i ~/.ssh/tfs-vm.key.pub tfs@10.0.2.10\n  # tfs@10.0.2.10's password: &lt;type tfs user's password: tfs123&gt;\nrm .ssh/known_hosts \n</code></pre> <ul> <li>In VSCode, click left \"Explorer\" panel to expand, if not expanded, and click \"Open Folder\" button.</li> <li>Choose \"/home/tfs/\"</li> <li>Type tfs user's password when asked</li> <li>Trust authors of the \"/home/tfs [SSH: TFS-VM]\" folder when asked</li> <li>Right click on the file \"tfs-vm.key\" in the file explorer</li> <li>Select \"Download...\" option</li> <li>Download the file into your user's accout \".ssh\" folder</li> <li> <p>Delete files \"tfs-vm.key\" and \"tfs-vm.key.pub\" on the TFS-VM.</p> </li> <li> <p>In VSCode, click left \"Remote Explorer\" panel to expand</p> </li> <li>Click the \"gear\" icon next to \"SSH TARGETS\" on top of \"Remote Explorer\" bar</li> <li>Choose to edit \"&lt;...&gt;/.ssh/config\" file (or equivalent)</li> <li>Find entry \"Host TFS-VM\" and update it as follows:</li> </ul> <pre><code>Host TFS-VM\n    HostName 127.0.0.1\n    Port 2200\n    ForwardX11 no\n    User tfs\n    IdentityFile \"&lt;path to the downloaded identity private key file&gt;\"\n</code></pre> <ul> <li>Save the file</li> <li>From now, VSCode will use the identity file to connect to the TFS-VM instead of the user's password.</li> </ul> Install VSCode Python Extension (in VSCode server) <p> This step installs Python extensions in VSCode server running in the VM.</p> <ul> <li>In VSCode (connected to the VM), click left button \"Extensions\"</li> <li>Search \"Python\" extension in the extension Marketplace.</li> <li> <p>Install official \"Python\" extension released by Microsoft.</p> <ul> <li>By default, since you're connected to the VM, it will be installed in the VSCode server running in the VM.</li> </ul> </li> <li> <p>In VSCode (connected to the VM), click left button \"Explorer\"</p> </li> <li>Click \"Ctrl+Alt+P\" and type \"Python: Select Interpreter\". Select option \"Python: 3.9.13 64-bit ('tfs')\"</li> </ul> Define environment variables for VSCode <p> The source code in the TFS controller project is hosted in folder <code>src/</code>. To help VSCode find the Python modules and packages, add the following file into your working space root folder:</p> <pre><code>echo \"PYTHONPATH=./src\" &gt;&gt; ~/tfs-ctrl/.env\n</code></pre>"},{"location":"development_guide/development_guide/#23-develop-a-component-wip","title":"2.3. Develop A Component (WIP)","text":"<p>Page under construction</p>"}]}
\ No newline at end of file
diff --git a/public/develop/sitemap.xml b/public/develop/sitemap.xml
index 313e9c1..d007ed2 100644
--- a/public/develop/sitemap.xml
+++ b/public/develop/sitemap.xml
@@ -24,56 +24,4 @@
          <loc>https://tfs.etsi.org/develop/development_guide/development_guide/</loc>
          <lastmod>2024-10-21</lastmod>
     </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/postman/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/robotframework/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_access_control_policy/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_auditing_service/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_discover_service/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_events_service/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_invoker_management/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_logging_service/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_provider_management/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_publish_service/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/api_security_service/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
-    <url>
-         <loc>https://tfs.etsi.org/develop/testing/testplan/common_operations/</loc>
-         <lastmod>2024-10-21</lastmod>
-    </url>
 </urlset>
\ No newline at end of file
diff --git a/public/develop/sitemap.xml.gz b/public/develop/sitemap.xml.gz
index 1a21b4456f7e7f056b86ea788dd04f61edd8a60e..29e0d45dd12d27ac5126996fcb8fc2df6f34878e 100644
GIT binary patch
delta 234
zcmV<G02TlK0{8)t7Jt2yF>k^!5QTSsMdUqp5;2r2F=Amyg1L(9YhuZ<Bj1I<zsCs(
zwJ^0qZaLr6^ZQPgTy8I&P0kR|cvrEUXDk7yyf&_>*y*@WKiF2T${|<;N}}0e#ag2N
zQ;2aKIU0hl?veY@2vltxP&`DD@ePx!B-RvgKh0HIujG`1F=K|lkprQbBQ%`B`d*Y`
zvi!VJBXwTOA}iKuo~1<|Ef4LE5KqRRY5Uz_VPYLr8(&G$5MW_+01GvO^8~msT0?LB
kwF5_A&0sXV3rp`a_g@RWD*xVSZt>U18_p?;(`5qy04;NE*#H0l

delta 369
zcmV-%0gnFo0saDz7JtoFJ#T|B5Z&`D5PL9*I<yrb>XN-uJ0r(jh!x|rd<L3---AR^
zKc=b@v6qAA<GrUdwy)TJv?l4nlSaEqS6QAWU=`NdHk<VQZMS?(x8<Vfydek)CtKR2
z#}M4J5W_HJqyx0lQHH(|q>lVT;tGm9drHei!eb=3JWZo8sDH|lg_tHBD1$(HqNt$<
zgH9A;O!@kSq|jnruJiT7a+NRFD^9s$7YT9G__NyX<#lF7>D7^|q(bLmW@!%wB!R^M
zG_!OK&fvKP8>*($HT(wV_A|wAhJGURI^s16y!V7dCY1J0>K^wP4qmn}pg-No#2B5q
zTMcgV(&<Vn1!_c<LK{4q%AwKf9EGv2)+1UG_+BfB!BeeCA>S!6dEz-6C?-eR_ITnV
z@h+DQj0a8(t_(I!WWSU1*z-XgTcupLH=2$yRf<4$UWaomo)oq%+6o<b8MwjxN4qfv
PZb8dWq=2GivI+nIFQu_-

diff --git a/public/develop/testing/postman/CAPIF.postman_collection.json b/public/develop/testing/postman/CAPIF.postman_collection.json
deleted file mode 100644
index e59a534..0000000
--- a/public/develop/testing/postman/CAPIF.postman_collection.json
+++ /dev/null
@@ -1,991 +0,0 @@
-{
-	"info": {
-		"_postman_id": "b512e528-4b13-4be2-aed2-a61a8381360e",
-		"name": "CAPIF",
-		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
-		"_exporter_id": "31608242",
-		"_collection_link": "https://red-comet-993867.postman.co/workspace/Team-Workspace~bfc7c442-a60c-4bb1-8730-fdabc2df89b9/collection/31608242-b512e528-4b13-4be2-aed2-a61a8381360e?action=share&source=collection_link&creator=31608242"
-	},
-	"item": [
-		{
-			"name": "01-login_admin",
-			"event": [
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"",
-							"pm.environment.set('REFRESH_TOKEN', res.refresh_token);",
-							"pm.environment.set('ADMIN_TOKEN', res.access_token);"
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				}
-			],
-			"request": {
-				"auth": {
-					"type": "basic",
-					"basic": [
-						{
-							"key": "password",
-							"value": "{{ADMIN_PASSWORD}}",
-							"type": "string"
-						},
-						{
-							"key": "username",
-							"value": "{{ADMIN_USER}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "POST",
-				"header": [],
-				"url": {
-					"raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/login",
-					"protocol": "https",
-					"host": [
-						"{{REGISTER_HOSTNAME}}"
-					],
-					"port": "{{REGISTER_PORT}}",
-					"path": [
-						"login"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "02-create_user",
-			"event": [
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"",
-							"pm.environment.set('USER_UUID', res.uuid);",
-							""
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				}
-			],
-			"request": {
-				"auth": {
-					"type": "bearer",
-					"bearer": [
-						{
-							"key": "token",
-							"value": "{{ADMIN_TOKEN}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "POST",
-				"header": [],
-				"body": {
-					"mode": "raw",
-					"raw": "{\n    \"username\": \"{{USER_NAME}}\",\n    \"password\": \"{{USER_PASSWORD}}\",\n    \"enterprise\": \"ETSI\",\n    \"country\": \"Spain\",\n    \"email\": \"example@gmail.com\",\n    \"purpose\": \"Use OpenCAPIF\",\n    \"phone_number\": \"+123456789\",\n    \"company_web\": \"www.etsi.com\",\n    \"description\": \"UserDescription\"\n}",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/createUser",
-					"protocol": "https",
-					"host": [
-						"{{REGISTER_HOSTNAME}}"
-					],
-					"port": "{{REGISTER_PORT}}",
-					"path": [
-						"createUser"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "03-getauth",
-			"event": [
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"",
-							"pm.environment.set('CA_ROOT', res.ca_root);",
-							"pm.environment.set('ACCESS_TOKEN', res.access_token);",
-							"pm.environment.set('ONBOARDING_URL', res.ccf_api_onboarding_url);",
-							"pm.environment.set('PUBLISH_URL', res.ccf_publish_url);",
-							"pm.environment.set('DISCOVER_URL', res.ccf_discover_url);",
-							"pm.environment.set('SECURITY_URL', res.ccf_security_url);",
-							"pm.environment.set('ONBOARDING_URL_INVOKER', res.ccf_onboarding_url);",
-							"",
-							"setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/write_ca',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: res",
-							"                    }",
-							"                }, function (err, res) {",
-							"                    console.log(res);",
-							"                });",
-							"            }, 5000);"
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				}
-			],
-			"request": {
-				"auth": {
-					"type": "basic",
-					"basic": [
-						{
-							"key": "password",
-							"value": "{{USER_PASSWORD}}",
-							"type": "string"
-						},
-						{
-							"key": "username",
-							"value": "{{USER_NAME}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "GET",
-				"header": [],
-				"url": {
-					"raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/getauth",
-					"protocol": "https",
-					"host": [
-						"{{REGISTER_HOSTNAME}}"
-					],
-					"port": "{{REGISTER_PORT}}",
-					"path": [
-						"getauth"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "04-onboard_provider",
-			"event": [
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"if (pm.response.code == 201){",
-							"    ",
-							"    pm.environment.set('PROVIDER_ID', res.apiProvDomId);",
-							"",
-							"    const roleVariableMapping = {",
-							"    \"AEF\": { id: 'AEF_ID', cert: 'AEF_CERT' },",
-							"    \"APF\": { id: 'APF_ID', cert: 'APF_CERT' },",
-							"    \"AMF\": { id: 'AMF_ID', cert: 'AMF_CERT' }",
-							"    };",
-							"",
-							"    res.apiProvFuncs.forEach(function(elemento) {",
-							"        const role = elemento.apiProvFuncRole;",
-							"        if (roleVariableMapping.hasOwnProperty(role)) {",
-							"            const variables = roleVariableMapping[role];",
-							"            pm.environment.set(variables.id, elemento.apiProvFuncId);",
-							"            pm.environment.set(variables.cert, elemento.regInfo.apiProvCert);",
-							"",
-							"        }",
-							"    });",
-							"",
-							"}",
-							"",
-							"",
-							""
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				},
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"",
-							"var res = JSON.parse(pm.request.body.raw);",
-							"",
-							"res.apiProvFuncs.forEach(function(elemento) {",
-							"",
-							"    setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/generate_csr',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: elemento",
-							"                    }",
-							"                }, function (err, response) {",
-							"                    j_file = JSON.parse(response.text());",
-							"                    elemento.regInfo.apiProvPubKey = j_file.csr;",
-							"                    pm.environment.set(elemento.apiProvFuncRole+'_KEY', j_file.key);",
-							"                });",
-							"            }, 5000);",
-							"",
-							"});",
-							"",
-							"pm.request.body.raw = res;"
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": true
-			},
-			"request": {
-				"auth": {
-					"type": "bearer",
-					"bearer": [
-						{
-							"key": "token",
-							"value": "{{ACCESS_TOKEN}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "POST",
-				"header": [
-					{
-						"key": "",
-						"value": "",
-						"type": "text",
-						"disabled": true
-					}
-				],
-				"body": {
-					"mode": "raw",
-					"raw": "{\n\"apiProvFuncs\": [\n    {\n    \"regInfo\": {\n        \"apiProvPubKey\": \"\"\n    },\n    \"apiProvFuncRole\": \"AEF\",\n    \"apiProvFuncInfo\": \"dummy_aef\"\n    },\n    {\n    \"regInfo\": {\n        \"apiProvPubKey\": \"\"\n    },\n    \"apiProvFuncRole\": \"APF\",\n    \"apiProvFuncInfo\": \"dummy_apf\"\n    },\n    {\n    \"regInfo\": {\n        \"apiProvPubKey\": \"\"\n    },\n    \"apiProvFuncRole\": \"AMF\",\n    \"apiProvFuncInfo\": \"dummy_amf\"\n    }\n],\n\"apiProvDomInfo\": \"This is provider\",\n\"suppFeat\": \"fff\",\n\"failReason\": \"string\",\n\"regSec\": \"{{ACCESS_TOKEN}}\"\n}",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL}}",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"{{ONBOARDING_URL}}"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "05-publish_api",
-			"event": [
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/write_cert',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: {cert: pm.environment.get('APF_CERT'), key:pm.environment.get('APF_KEY')}",
-							"                    }",
-							"                }, function (err, response) {",
-							"                    console.log(response)",
-							"                });",
-							"            }, 5000);",
-							"",
-							"",
-							""
-						],
-						"type": "text/javascript"
-					}
-				},
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							""
-						],
-						"type": "text/javascript"
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": true
-			},
-			"request": {
-				"auth": {
-					"type": "noauth"
-				},
-				"method": "POST",
-				"header": [
-					{
-						"key": "",
-						"value": "",
-						"type": "text",
-						"disabled": true
-					}
-				],
-				"body": {
-					"mode": "raw",
-					"raw": "\n{\n    \"apiName\": \"hello_api_demo_v2\",\n    \"aefProfiles\": [\n      {\n        \"aefId\": \"{{AEF_ID}}\",\n        \"versions\": [\n          {\n            \"apiVersion\": \"v1\",\n            \"expiry\": \"2021-11-30T10:32:02.004Z\",\n            \"resources\": [\n              {\n                \"resourceName\": \"hello-endpoint\",\n                \"commType\": \"REQUEST_RESPONSE\",\n                \"uri\": \"/hello\",\n                \"custOpName\": \"string\",\n                \"operations\": [\n                  \"POST\"\n                ],\n                \"description\": \"Endpoint to receive a welcome message\"\n              }\n            ],\n            \"custOperations\": [\n              {\n                \"commType\": \"REQUEST_RESPONSE\",\n                \"custOpName\": \"string\",\n                \"operations\": [\n                  \"POST\"\n                ],\n                \"description\": \"string\"\n              }\n            ]\n          }\n        ],\n        \"protocol\": \"HTTP_1_1\",\n        \"dataFormat\": \"JSON\",\n        \"securityMethods\": [\"Oauth\"],\n        \"interfaceDescriptions\": [\n          {\n            \"ipv4Addr\": \"localhost\",\n            \"port\": 8088,\n            \"securityMethods\": [\"Oauth\"]\n          }\n        ]\n      }\n    ],\n    \"description\": \"Hello api services\",\n    \"supportedFeatures\": \"fffff\",\n    \"shareableInfo\": {\n      \"isShareable\": true,\n      \"capifProvDoms\": [\n        \"string\"\n      ]\n    },\n    \"serviceAPICategory\": \"string\",\n    \"apiSuppFeats\": \"fffff\",\n    \"pubApiPath\": {\n      \"ccfIds\": [\n        \"string\"\n      ]\n    },\n    \"ccfId\": \"string\"\n  }",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/published-apis/v1/{{APF_ID}}/service-apis",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"published-apis",
-						"v1",
-						"{{APF_ID}}",
-						"service-apis"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "06-onboard_invoker",
-			"event": [
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"if (pm.response.code == 201){",
-							"    ",
-							"    pm.environment.set('INVOKER_ID', res.apiInvokerId);",
-							"    pm.environment.set('INVOKER_CERT', res.onboardingInformation.apiInvokerCertificate);",
-							"}",
-							"",
-							"",
-							""
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				},
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"",
-							"var res = JSON.parse(pm.request.body.raw);",
-							"",
-							"",
-							"setTimeout(() => {",
-							"            pm.sendRequest({",
-							"                url: 'http://localhost:3000/generate_csr_invoker',",
-							"                method: 'POST',",
-							"                header: 'Content-Type:application/json',",
-							"                encoding: 'binary',",
-							"                body: {",
-							"                    mode: 'raw',",
-							"                    raw: {}",
-							"                }",
-							"            }, function (err, response) {",
-							"                j_file = JSON.parse(response.text());",
-							"                res.onboardingInformation.apiInvokerPublicKey = j_file.csr;",
-							"                pm.environment.set('INVOKER_KEY', j_file.key);",
-							"            });",
-							"        }, 5000);",
-							"",
-							"",
-							"pm.request.body.raw = res;"
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": true
-			},
-			"request": {
-				"auth": {
-					"type": "bearer",
-					"bearer": [
-						{
-							"key": "token",
-							"value": "{{ACCESS_TOKEN}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "POST",
-				"header": [
-					{
-						"key": "",
-						"value": "",
-						"type": "text",
-						"disabled": true
-					}
-				],
-				"body": {
-					"mode": "raw",
-					"raw": "{\n  \"notificationDestination\" : \"http://host.docker.internal:8086/netapp_callback\",\n  \"supportedFeatures\" : \"fffffff\",\n  \"apiInvokerInformation\" : \"dummy\",\n  \"websockNotifConfig\" : {\n    \"requestWebsocketUri\" : true,\n    \"websocketUri\" : \"websocketUri\"\n  },\n  \"onboardingInformation\" : {\n    \"apiInvokerPublicKey\" : \"\"\n  },\n  \"requestTestNotification\" : true\n}",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL_INVOKER}}",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"{{ONBOARDING_URL_INVOKER}}"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "07-discover",
-			"event": [
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/write_cert',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}",
-							"                    }",
-							"                }, function (err, response) {",
-							"                    console.log(response)",
-							"                });",
-							"            }, 5000);",
-							"",
-							"",
-							""
-						],
-						"type": "text/javascript"
-					}
-				},
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"if (pm.response.code == 200){",
-							"",
-							"    res.serviceAPIDescriptions.forEach(function(api) {",
-							"        pm.environment.set('API_SERVICE_ID', api.apiId);",
-							"        pm.environment.set('API_NAME', api.apiName);",
-							"        pm.environment.set('API_AEF_ID', api.aefProfiles[0].aefId);",
-							"        pm.environment.set('IPV4ADDR', api.aefProfiles[0].interfaceDescriptions[0].ipv4Addr);",
-							"        pm.environment.set('PORT', api.aefProfiles[0].interfaceDescriptions[0].port);",
-							"        pm.environment.set('URI', api.aefProfiles[0].versions[0].resources[0].uri);",
-							"    });",
-							"}"
-						],
-						"type": "text/javascript"
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"disableBodyPruning": true,
-				"strictSSL": true
-			},
-			"request": {
-				"auth": {
-					"type": "noauth"
-				},
-				"method": "GET",
-				"header": [
-					{
-						"key": "",
-						"value": "",
-						"type": "text",
-						"disabled": true
-					}
-				],
-				"body": {
-					"mode": "raw",
-					"raw": "",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/{{DISCOVER_URL}}{{INVOKER_ID}}",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"{{DISCOVER_URL}}{{INVOKER_ID}}"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "08-security_context",
-			"event": [
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/write_cert',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}",
-							"                    }",
-							"                }, function (err, response) {",
-							"                    console.log(response)",
-							"                });",
-							"            }, 5000);",
-							"",
-							"",
-							""
-						],
-						"type": "text/javascript"
-					}
-				},
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							""
-						],
-						"type": "text/javascript"
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": true
-			},
-			"request": {
-				"auth": {
-					"type": "noauth"
-				},
-				"method": "PUT",
-				"header": [
-					{
-						"key": "",
-						"value": "",
-						"type": "text",
-						"disabled": true
-					}
-				],
-				"body": {
-					"mode": "raw",
-					"raw": "{\n  \"securityInfo\": [\n    {\n      \"prefSecurityMethods\": [\n        \"Oauth\"\n      ],\n      \"authenticationInfo\": \"string\",\n      \"authorizationInfo\": \"string\",\n      \"aefId\": \"{{API_AEF_ID}}\",\n      \"apiId\": \"{{API_SERVICE_ID}}\"\n    }\n  ],\n  \"notificationDestination\": \"https://mynotificationdest.com\",\n  \"requestTestNotification\": true,\n  \"websockNotifConfig\": {\n    \"websocketUri\": \"string\",\n    \"requestWebsocketUri\": true\n  },\n  \"supportedFeatures\": \"fff\"\n}",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/capif-security/v1/trustedInvokers/{{INVOKER_ID}}",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"capif-security",
-						"v1",
-						"trustedInvokers",
-						"{{INVOKER_ID}}"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "09-get_token",
-			"event": [
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/write_cert',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}",
-							"                    }",
-							"                }, function (err, response) {",
-							"                    console.log(response)",
-							"                });",
-							"            }, 5000);",
-							"",
-							"",
-							""
-						],
-						"type": "text/javascript"
-					}
-				},
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"if (pm.response.code == 200){",
-							"    pm.environment.set('NETAPP_SERVICE_TOKEN', res.access_token);",
-							"}"
-						],
-						"type": "text/javascript"
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": true,
-				"disabledSystemHeaders": {}
-			},
-			"request": {
-				"auth": {
-					"type": "noauth"
-				},
-				"method": "POST",
-				"header": [
-					{
-						"key": "",
-						"value": "",
-						"type": "text",
-						"disabled": true
-					}
-				],
-				"body": {
-					"mode": "urlencoded",
-					"urlencoded": [
-						{
-							"key": "client_id",
-							"value": "{{INVOKER_ID}}",
-							"type": "text"
-						},
-						{
-							"key": "grant_type",
-							"value": "client_credentials",
-							"type": "text"
-						},
-						{
-							"key": "client_secret",
-							"value": "string",
-							"type": "text"
-						},
-						{
-							"key": "scope",
-							"value": "3gpp#{{API_AEF_ID}}:{{API_NAME}}",
-							"type": "text"
-						}
-					]
-				},
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/capif-security/v1/securities/{{INVOKER_ID}}/token",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"capif-security",
-						"v1",
-						"securities",
-						"{{INVOKER_ID}}",
-						"token"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "10-call_service",
-			"event": [
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							""
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				},
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							""
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": false
-			},
-			"request": {
-				"auth": {
-					"type": "bearer",
-					"bearer": [
-						{
-							"key": "token",
-							"value": "{{NETAPP_SERVICE_TOKEN}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "POST",
-				"header": [
-					{
-						"key": "",
-						"value": "",
-						"type": "text",
-						"disabled": true
-					}
-				],
-				"body": {
-					"mode": "raw",
-					"raw": "{\n\"name\": {{USER_NAME}}\n}",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "http://{{IPV4ADDR}}:{{PORT}}{{URI}}",
-					"protocol": "http",
-					"host": [
-						"{{IPV4ADDR}}"
-					],
-					"port": "{{PORT}}{{URI}}"
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "offboard_provider",
-			"event": [
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/write_cert',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: {cert: pm.environment.get('AMF_CERT'), key:pm.environment.get('AMF_KEY')}",
-							"                    }",
-							"                }, function (err, response) {",
-							"                    console.log(response)",
-							"                });",
-							"            }, 5000);"
-						],
-						"type": "text/javascript"
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": true
-			},
-			"request": {
-				"auth": {
-					"type": "noauth"
-				},
-				"method": "DELETE",
-				"header": [],
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL}}/{{PROVIDER_ID}}",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"{{ONBOARDING_URL}}",
-						"{{PROVIDER_ID}}"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "offboard_invoker",
-			"event": [
-				{
-					"listen": "prerequest",
-					"script": {
-						"exec": [
-							"setTimeout(() => {",
-							"                pm.sendRequest({",
-							"                    url: 'http://localhost:3000/write_cert',",
-							"                    method: 'POST',",
-							"                    header: 'Content-Type:application/json',",
-							"                    encoding: 'binary',",
-							"                    body: {",
-							"                        mode: 'raw',",
-							"                        raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}",
-							"                    }",
-							"                }, function (err, response) {",
-							"                    console.log(response)",
-							"                });",
-							"            }, 5000);"
-						],
-						"type": "text/javascript"
-					}
-				}
-			],
-			"protocolProfileBehavior": {
-				"strictSSL": true
-			},
-			"request": {
-				"auth": {
-					"type": "noauth"
-				},
-				"method": "DELETE",
-				"header": [],
-				"url": {
-					"raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL_INVOKER}}/{{INVOKER_ID}}",
-					"protocol": "https",
-					"host": [
-						"{{CAPIF_HOSTNAME}}"
-					],
-					"path": [
-						"{{ONBOARDING_URL_INVOKER}}",
-						"{{INVOKER_ID}}"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "remove_user",
-			"request": {
-				"auth": {
-					"type": "bearer",
-					"bearer": [
-						{
-							"key": "token",
-							"value": "{{ADMIN_TOKEN}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "DELETE",
-				"header": [],
-				"body": {
-					"mode": "raw",
-					"raw": "",
-					"options": {
-						"raw": {
-							"language": "json"
-						}
-					}
-				},
-				"url": {
-					"raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/deleteUser/{{USER_UUID}}",
-					"protocol": "https",
-					"host": [
-						"{{REGISTER_HOSTNAME}}"
-					],
-					"port": "{{REGISTER_PORT}}",
-					"path": [
-						"deleteUser",
-						"{{USER_UUID}}"
-					]
-				}
-			},
-			"response": []
-		},
-		{
-			"name": "refresh_admin_token",
-			"event": [
-				{
-					"listen": "test",
-					"script": {
-						"exec": [
-							"var res = JSON.parse(responseBody);",
-							"",
-							"pm.environment.set('REFRESH_TOKEN', res.refresh_token);"
-						],
-						"type": "text/javascript",
-						"packages": {}
-					}
-				}
-			],
-			"request": {
-				"auth": {
-					"type": "bearer",
-					"bearer": [
-						{
-							"key": "token",
-							"value": "{{REFRESH_TOKEN}}",
-							"type": "string"
-						}
-					]
-				},
-				"method": "POST",
-				"header": [],
-				"url": {
-					"raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/refresh",
-					"protocol": "https",
-					"host": [
-						"{{REGISTER_HOSTNAME}}"
-					],
-					"port": "{{REGISTER_PORT}}",
-					"path": [
-						"refresh"
-					]
-				}
-			},
-			"response": []
-		}
-	]
-}
\ No newline at end of file
diff --git a/public/develop/testing/postman/CAPIF.postman_environment.json b/public/develop/testing/postman/CAPIF.postman_environment.json
deleted file mode 100644
index 0ed42a9..0000000
--- a/public/develop/testing/postman/CAPIF.postman_environment.json
+++ /dev/null
@@ -1,267 +0,0 @@
-{
-	"id": "872bffef-37ef-4a25-afa8-6a61de256f4b",
-	"name": "CAPIF",
-	"values": [
-		{
-			"key": "CAPIF_HOSTNAME",
-			"value": "capifcore",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "CAPIF_PORT",
-			"value": "8080",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "REGISTER_HOSTNAME",
-			"value": "localhost",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "REGISTER_PORT",
-			"value": "8084",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "USERNAME",
-			"value": "ProviderONE",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "PASSWORD",
-			"value": "pass",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "CALLBACK_IP",
-			"value": "host.docker.internal",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "CALLBACK_PORT",
-			"value": "8087",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "ADMIN_USER",
-			"value": "admin",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "ADMIN_PASSWORD",
-			"value": "password123",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "ADMIN_TOKEN",
-			"value": "",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "REFRESH_TOKEN",
-			"value": "",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "USER_NAME",
-			"value": "custom_user",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "USER_PASSWORD",
-			"value": "user_pass",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "USER_UUID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "ONBOARDING_URL",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "PUBLISH_URL",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "ONBOARDING_URL_INVOKER",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "DISCOVER_URL",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "SECURITY_URL",
-			"value": "",
-			"type": "default",
-			"enabled": true
-		},
-		{
-			"key": "CA_ROOT",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "ACCESS_TOKEN",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "APF_KEY",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "AMF_KEY",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "AEF_KEY",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "PROVIDER_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "AEF_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "AEF_CERT",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "APF_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "APF_CERT",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "AMF_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "AMF_CERT",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "INVOKER_KEY",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "INVOKER_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "INVOKER_CERT",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "API_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "API_NAME",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "IPV4ADDR",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "PORT",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "URI",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "API_SERVICE_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "API_AEF_ID",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		},
-		{
-			"key": "NETAPP_SERVICE_TOKEN",
-			"value": "",
-			"type": "any",
-			"enabled": true
-		}
-	],
-	"_postman_variable_scope": "environment",
-	"_postman_exported_at": "2024-06-26T11:17:13.183Z",
-	"_postman_exported_using": "Postman/11.2.13"
-}
\ No newline at end of file
diff --git a/public/develop/testing/postman/hello_api.py b/public/develop/testing/postman/hello_api.py
deleted file mode 100644
index 0b2a359..0000000
--- a/public/develop/testing/postman/hello_api.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from flask import Flask, jsonify, request
-from flask_jwt_extended import jwt_required, JWTManager, get_jwt_identity, get_jwt
-import ssl
-from werkzeug import serving
-import socket, ssl
-import OpenSSL
-from OpenSSL import crypto
-import jwt
-import pyone
-
-app = Flask(__name__)
-
-jwt_flask = JWTManager(app)
-
-
-with open("Responses/cert_server.pem", "rb") as cert_file:
-            cert= cert_file.read()
-
-crtObj = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
-pubKeyObject = crtObj.get_pubkey()
-pubKeyString = crypto.dump_publickey(crypto.FILETYPE_PEM,pubKeyObject)
-
-app.config['JWT_ALGORITHM'] = 'RS256'
-app.config['JWT_PUBLIC_KEY'] = pubKeyString
-
-
-@app.route("/hello", methods=["POST"])
-@jwt_required()
-def hello():
-
-    request_data = request.get_json()
-
-    user_name = request_data['name']
-
-    return jsonify(f"Hello: {user_name}, welcome to CAPIF.")
-
-if __name__ == '__main__':
-    serving.run_simple("0.0.0.0", 8088, app)
diff --git a/public/develop/testing/postman/index.html b/public/develop/testing/postman/index.html
deleted file mode 100644
index 4917d23..0000000
--- a/public/develop/testing/postman/index.html
+++ /dev/null
@@ -1,510 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/postman/">
-      
-      
-      
-      
-      <link rel="icon" href="../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Postman - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#postman" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Postman
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="postman">Postman</h1>
-<p>In this section we can use Postman to publish an API as a provider and use it as an invoker.</p>
-<h2 id="requisites">Requisites</h2>
-<ul>
-<li>We will need to have Node.js installed since we will use a small script to create the CSRs of the certificates.</li>
-<li>An instance of CAPIF (If it is not local, certain variables would have to be modified both in the Node.js script and in the Postman environment variables).</li>
-</ul>
-<h2 id="first-steps">First steps</h2>
-<ol>
-<li>Install the Node dependencies <a href="./package.json" download>package.json</a> to run the script with:</li>
-</ol>
-<pre><code>npm i
-</code></pre>
-<ol>
-<li>Run the <a href="./script.js" download>script.js</a> with the following command:</li>
-</ol>
-<pre><code>node script.js
-</code></pre>
-<ol>
-<li>Import Postman collection and environment variables (<a href="./CAPIF.postman_collection.json" download>CAPIF.postman_collection.json</a> and <a href="./CAPIF.postman_environment.json" download>CAPIF.postman_environment.json</a>)</li>
-<li>Select CAPIF Environment before start testing.</li>
-</ol>
-<h2 id="remote-capif">Remote CAPIF</h2>
-<p>If the CAPIF is not local, the host and port of both the CAPIF and the register would have to be specified in the variables, and the CAPIF_HOSTNAME in the script, necessary to obtain the server certificate.</p>
-<p><strong>Enviroments in Postman</strong></p>
-<pre><code>CAPIF_HOSTNAME     capifcore
-CAPIF_PORT         8080
-REGISTER_HOSTNAME  register
-REGISTER_PORT      8084
-</code></pre>
-<p><strong>Const in script.js</strong></p>
-<pre><code>CAPIF_HOSTNAME    capifcore
-</code></pre>
-<h2 id="capif-flows">CAPIF Flows</h2>
-<p>Once the first steps have been taken, we can now use Postman requests. These requests are numbered in the order that must be followed to obtain everything necessary from CAPIF.</p>
-<h3 id="creation-of-user-by-admin">Creation of User by Admin</h3>
-<p>The first step would be for an administrator to create a user with which a provider and an invoker will be created. To do this, the admin must log in to obtain the token needed in admin requests.</p>
-<h4 id="01-login_admin"><strong>01-Login_admin</strong></h4>
-<p><img alt="Flow" src="../../images/flows/01_Login_Admin.png" /></p>
-<h4 id="02-creation-of-user"><strong>02-Creation of User</strong></h4>
-<p><img alt="Flow" src="../../images/flows/02_Creation_of_user.png" /></p>
-<h3 id="publication-of-an-api">Publication of an API</h3>
-<p>The next step is to register a provider using the user created by the administrator in order to publish an API.</p>
-<h4 id="03-getauth_provider"><strong>03-getauth_provider</strong></h4>
-<p><img alt="Flow" src="../../images/flows/03_Register_of_AEF_GetAuth.png" /></p>
-<h4 id="04-onboard_provider"><strong>04-onboard_provider</strong></h4>
-<p><img alt="Flow" src="../../images/flows/04_AEF_API_Provider_registration.png" /></p>
-<p>At this point we move on to using certificate authentication in CAPIF. In Postman it is necessary to add the certificates manually and using more than one certificate for the same host as we do in CAPIF complicates things. For this reason, we use the script to overwrite a certificate and a key when it is necessary to have a specific one.</p>
-<p>To configure go to <strong>settings</strong> in Postman and open the <strong>certificates</strong> section. </p>
-<ul>
-<li>Here, activate the <strong>CA certificates</strong> option and add the <strong>ca_cert.pem</strong> file found in the <strong>Responses</strong> folder.</li>
-<li>Adds a client certificate specifying the CAPIF host being used and the files <strong>client_cert.crt</strong> and <strong>client_key.key</strong> in the <strong>Responses</strong> folder.</li>
-</ul>
-<p>Once this is done, the node script will be in charge of changing the certificate that is necessary in each request.</p>
-<h4 id="05-publish_api"><strong>05-publish_api</strong></h4>
-<p><img alt="Flow" src="../../images/flows/05_AEF_Publish.png" /></p>
-<p>Once the api is published, we can start it. In this case we have a test one created in python called <a href="./hello_api.py" download>hello_api.py</a> that can be executed with the following command:</p>
-<pre><code>python3 hello_api.py
-</code></pre>
-<p>The API publication interface is set to localhost with port 8088, so the service must be set up locally. If you wanted to build it on another site, you would have to change the interface description in the body of publish_api.</p>
-<p>With this the provider part would be finished.</p>
-<h3 id="calling-the-api">Calling the API</h3>
-<p>Finally, we will create an invoker with the user given by the administrator to be able to use the published api.</p>
-<h4 id="06-getauth_invoker"><strong>06-getauth_invoker</strong></h4>
-<p><img alt="Flow" src="../../images/flows/06_Invoker_Register_GetAuth.png" /></p>
-<h4 id="07-onboard_invoker"><strong>07-onboard_invoker</strong></h4>
-<p><img alt="Flow" src="../../images/flows/07_Invoker_Onboarding.png" /></p>
-<p>At this point we move on to using certificate authentication in CAPIF. <strong>If you did not configure the provider's certificates, you would have to do it now</strong>.</p>
-<h4 id="08-discover"><strong>08-discover</strong></h4>
-<p><img alt="Flow" src="../../images/flows/08_Invoker_Discover_AEF.png" /></p>
-<h4 id="09-security_context"><strong>09-security_context</strong></h4>
-<p><img alt="Flow" src="../../images/flows/09_Invoker_Create_Security_Context.png" /></p>
-<h4 id="10-get_token"><strong>10-get_token</strong></h4>
-<p><img alt="Flow" src="../../images/flows/10_Invoker_Get_Token.png" /></p>
-<h4 id="11-call_service"><strong>11-call_service</strong></h4>
-<p><img alt="Flow" src="../../images/flows/11_Invoker_Send_Request_to_AEF_Service_API.png" /></p>
-<p>With this, we would have made the API call and finished the flow.</p>
-<h3 id="other-requests">Other requests</h3>
-<p>Other requests that we have added are the following:</p>
-<ul>
-<li><strong>offboard_provider</strong>      Performs offboarding of the provider, thereby eliminating the published APIs.</li>
-<li><strong>offboard_invoker</strong>       Offboards the invoker, also eliminating access to the APIs of that invoker.</li>
-<li><strong>remove_user</strong>            Delete the user.</li>
-<li><strong>refresh_admin_token</strong>    Return a new access token to the admin.</li>
-</ul>
-<h2 id="notes">Notes</h2>
-<ul>
-<li>This process is designed to teach how requests are made in Postman and the flow that should be followed to publish and use an API.</li>
-<li>It is possible that if external CAPIFs are used (Public CAPIF) the test data may already be used or the API already registered.</li>
-<li>It is necessary to have the Node service running to make the certificate change for the requests, otherwise it will not work.</li>
-<li>We are working on adding more requests to the Postman collection.</li>
-<li>This collection is a testing guide and is recommended for testing purposes only.</li>
-</ul>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/postman/package.json b/public/develop/testing/postman/package.json
deleted file mode 100644
index 6d612a7..0000000
--- a/public/develop/testing/postman/package.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "name": "node-server",
-    "version": "1.0.0",
-    "description": "",
-    "main": "index.js",
-    "scripts": {
-      "test": "echo \"Error: no test specified\" && exit 1"
-    },
-    "author": "",
-    "license": "ISC",
-    "dependencies": {
-      "body-parser": "^1.18.3",
-      "express": "^4.16.3",
-      "shelljs": "^0.8.2"
-    }
-  }
\ No newline at end of file
diff --git a/public/develop/testing/postman/script.js b/public/develop/testing/postman/script.js
deleted file mode 100644
index 980f81f..0000000
--- a/public/develop/testing/postman/script.js
+++ /dev/null
@@ -1,199 +0,0 @@
-// Change this variable if another host is used for CAPIF
-const CAPIF_HOSTNAME = 'capifcore';
-
-const express = require('express'),
-  app = express(),
-  fs = require('fs'),
-  shell = require('shelljs'),
-
-
-  folderPath = './Responses/',
-  bodyParser = require('body-parser'),
-  path = require('path');
-
-const { exec } = require('child_process');
-
-// Create the folder path in case it doesn't exist
-shell.mkdir('-p', folderPath);
-
- // Change the limits according to your response size
-app.use(bodyParser.json({limit: '50mb', extended: true}));
-app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); 
-var opensslCommand = ''
-
-if (CAPIF_HOSTNAME.includes(':')){
-  opensslCommand = `openssl s_client -connect ${CAPIF_HOSTNAME} | openssl x509 -text > ./Responses/cert_server.pem`;
-}
-else{
-  opensslCommand = `openssl s_client -connect ${CAPIF_HOSTNAME}:443 | openssl x509 -text > ./Responses/cert_server.pem`;
-}
-
-exec(opensslCommand, (error, stdout, stderr) => {
-  if (error) {
-    console.error(`Error generating CSR: ${stderr}`);
-  }
-});
-
-fs.writeFileSync('./Responses/client_cert.crt', '');
-fs.writeFileSync('./Responses/client_key.key', '');
-
-app.get('/', (req, res) => res.send('Hello, I write data to file. Send them requests!'));
-
-app.post('/generate_csr', (req, res) => {
-
-  console.log(req.body);
-  const csrFilePath = 'Responses/'+req.body.apiProvFuncRole+'_csr.pem';
-  const privateKeyFilePath = 'Responses/'+req.body.apiProvFuncRole+'_key.key';
-
-  const subjectInfo = {
-    country: 'ES',
-    state: 'Madrid',
-    locality: 'Madrid',
-    organization: 'Telefonica I+D',
-    organizationalUnit: 'IT Department',
-    emailAddress: 'admin@example.com',
-  };
-
-  const opensslCommand = `openssl req -newkey rsa:2048 -nodes -keyout ${privateKeyFilePath} -out ${csrFilePath} -subj "/C=${subjectInfo.country}/ST=${subjectInfo.state}/L=${subjectInfo.locality}/O=${subjectInfo.organization}/OU=${subjectInfo.organizationalUnit}/emailAddress=${subjectInfo.emailAddress}"`;
-
-  exec(opensslCommand, (error, stdout, stderr) => {
-    if (error) {
-      console.error(`Error generating CSR: ${stderr}`);
-    } else {
-      console.log('CSR generated successfully:');
-      fs.readFile(csrFilePath, 'utf8', (readError, csrContent) => {
-        if (readError) {
-          console.error(`Error reading CSR: ${readError}`);
-          res.status(500).send('Error reading CSR');
-        } else {
-          console.log('CSR read successfully:');
-          // Send the CSR content in the response
-          fs.readFile(privateKeyFilePath, 'utf8', (readError, keyContent) => {
-            if (readError) {
-              console.error(`Error reading KEY: ${readError}`);
-              res.status(500).send('Error reading KEY');
-            } else {
-              console.log('KEY read successfully:');
-              // Send the CSR content in the response
-              fs.unlink(csrFilePath, (err) => {
-                if (err) {
-                  console.error(`Error deleting file: ${err.message}`);
-                } 
-              });
-              fs.unlink(privateKeyFilePath, (err) => {
-                if (err) {
-                  console.error(`Error deleting file: ${err.message}`);
-                } 
-              });
-              res.send({csr: csrContent, key: keyContent});
-            }
-          });
-        }
-      });
-    }
-  });
-});
-
-app.post('/generate_csr_invoker', (req, res) => {
-
-  console.log(req.body);
-  const csrFilePath = 'Responses/invoker_csr.pem';
-  const privateKeyFilePath = 'Responses/invoker_key.key';
-
-  const subjectInfo = {
-    country: 'ES',
-    state: 'Madrid',
-    locality: 'Madrid',
-    organization: 'Telefonica I+D',
-    organizationalUnit: 'IT Department',
-    emailAddress: 'admin@example.com',
-  };
-
-  const opensslCommand = `openssl req -newkey rsa:2048 -nodes -keyout ${privateKeyFilePath} -out ${csrFilePath} -subj "/C=${subjectInfo.country}/ST=${subjectInfo.state}/L=${subjectInfo.locality}/O=${subjectInfo.organization}/OU=${subjectInfo.organizationalUnit}/emailAddress=${subjectInfo.emailAddress}"`;
-
-  exec(opensslCommand, (error, stdout, stderr) => {
-    if (error) {
-      console.error(`Error generating CSR: ${stderr}`);
-    } else {
-      console.log('CSR generated successfully:');
-      fs.readFile(csrFilePath, 'utf8', (readError, csrContent) => {
-        if (readError) {
-          console.error(`Error reading CSR: ${readError}`);
-          res.status(500).send('Error reading CSR');
-        } else {
-          console.log('CSR read successfuly:');
-          // Send the CSR content in the response
-          fs.readFile(privateKeyFilePath, 'utf8', (readError, keyContent) => {
-            if (readError) {
-              console.error(`Error reading KEY: ${readError}`);
-              res.status(500).send('Error reading KEY');
-            } else {
-              console.log('KEY read successfully:');
-              // Send the CSR content in the response
-              fs.unlink(csrFilePath, (err) => {
-                if (err) {
-                  console.error(`Error deleting file: ${err.message}`);
-                } 
-              });
-              fs.unlink(privateKeyFilePath, (err) => {
-                if (err) {
-                  console.error(`Error deleting file: ${err.message}`);
-                } 
-              });
-              res.send({csr: csrContent, key: keyContent});
-            }
-          });
-        }
-      });
-    }
-  });
-});
-
-
-app.post('/write_cert', (req, res) => {
-  let extension = 'crt',
-    fsMode = 'writeFile',
-    filename = "client_cert",
-    filePath = `${path.join(folderPath, filename)}.${extension}`,
-    options = {encoding: 'binary'};
-  fs[fsMode](filePath, req.body.cert, options, (err) => {
-    if (err) {
-      console.log(err);
-      res.send('Error');
-    }
-  });
-  extension = 'key';
-  filename = "client_key";
-  filePath = `${path.join(folderPath, filename)}.${extension}`;
-  fs[fsMode](filePath, req.body.key, options, (err) => {
-    if (err) {
-      console.log(err);
-      res.send('Error');
-    }
-    else {
-      res.send('Success');
-    }
-  });
-});
-
-app.post('/write_ca', (req, res) => {
-  let extension = 'pem',
-    fsMode = 'writeFile',
-    filename = "ca_cert",
-    filePath = `${path.join(folderPath, filename)}.${extension}`,
-    options = {encoding: 'binary'};
-  fs[fsMode](filePath, req.body.ca_root, options, (err) => {
-    if (err) {
-      console.log(err);
-      res.send('Error');
-    }
-    else {
-      res.send('Success');
-    }
-  });
-});
-
-app.listen(3000, () => {
-  console.log('ResponsesToFile App is listening now! Send them requests my way!');
-  console.log(`Data is being stored at location: ${path.join(process.cwd(), folderPath)}`);
-});
\ No newline at end of file
diff --git a/public/develop/testing/robotframework/index.html b/public/develop/testing/robotframework/index.html
deleted file mode 100644
index aff378e..0000000
--- a/public/develop/testing/robotframework/index.html
+++ /dev/null
@@ -1,543 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/robotframework/">
-      
-      
-      
-      
-      <link rel="icon" href="../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Robot Framework - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#robot-framework" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Robot Framework
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="robot-framework">Robot Framework</h1>
-<h2 id="steps-to-test">Steps to Test</h2>
-<p>To run any test locally you will need <em>docker</em> and <em>docker-compose</em> installed in order run services and execute test plan. Steps will be:</p>
-<ul>
-<li>
-<p><strong>Run All Services</strong>: See section <a href="../../gettingstarted/howtorun.md#run-all-capif-services-locally-with-docker-images">Run All CAPIF Services</a></p>
-</li>
-<li>
-<p><strong>Run desired tests</strong>: At this point we have 2 options:</p>
-</li>
-<li>
-<p><strong>Using helper script</strong>: <a href="#script-test-execution">Script Test Execution</a></p>
-</li>
-<li><strong>Build robot docker image and execute manually robot docker</strong>: <a href="#manual-build-and-test-execution">Manual Build And Test Execution</a></li>
-</ul>
-<h2 id="script-test-execution">Script Test Execution</h2>
-<p>This script will build robot docker image if it's need and execute tests selected by "include" option. Just go to service folder, execute and follow steps.</p>
-<pre><code>./run_capif_tests.sh --include &lt;TAG&gt;
-</code></pre>
-<p>Results will be stored at <REPOSITORY_FOLDER>/results</p>
-<p>Please check parameters (include) under <em>Test Execution</em> at <a href="#manual-build-and-test-execution">Manual Build And Test Execution</a>.</p>
-<h3 id="mock-server">Mock Server</h3>
-<p>Some tests on Test Plans require mockserver. That mock server must be deployed and reachable by Robot Framework and CCF under test.</p>
-<p>To run Mock Server locally you can just execute the next script:</p>
-<pre><code>cd services
-./run_mock_server.sh
-
-or
-./run.sh -s
-</code></pre>
-<p>If you want to launch only tests that not needed mockserver, just add "--exclude mockserver" parameter to robot execution:</p>
-<pre><code>./run_capif_tests.sh --include &lt;TAG&gt; --exclude mockserver
-</code></pre>
-<p>After run tests the Mock Server can be removed from local deployment:</p>
-<pre><code>./clean_mock_server.sh
-
-or
-./clean_capif_docker_services.sh -s
-</code></pre>
-<h2 id="manual-build-and-test-execution">Manual Build And Test Execution</h2>
-<ul>
-<li><strong>Build Robot docker image</strong>:</li>
-</ul>
-<pre><code>cd tools/robot
-docker build . -t capif-robot-test:latest
-</code></pre>
-<ul>
-<li><strong>Tests Execution</strong>:</li>
-</ul>
-<p>Execute all tests locally:</p>
-<pre><code>&lt;PATH_TO_REPOSITORY&gt;=path in local machine to repository cloned.
-&lt;PATH_RESULT_FOLDER&gt;=path to a folder on local machine to store results of Robot Framework execution.
-&lt;CAPIF_HOSTNAME&gt;=Is the hostname set when run.sh is executed, by default it is capifcore.
-&lt;CAPIF_HTTP_PORT&gt;=This is the port to reach when robot framework want to reach CAPIF deployment using http, this should be set to port without TLS set on Nginx, 8080 by default.
-&lt;CAPIF_HTTPS_PORT&gt;=This is the port to be used when we want to use https connection, this should be set to port with TLS set on Nginx, 443 by default
-&lt;CAPIF_REGISTER&gt;=This is the hostname of register service deployed. By default it is register.
-&lt;CAPIF_REGISTER_PORT&gt;=This is the port to be used to reach register service deployed. By default it is 8084.
-&lt;CAPIF_VAULT&gt;=This is the hostname of vault service. By default it is vault.
-&lt;CAPIF_VAULT_PORT&gt;=This is the port to be used to reach vault service. By default it is 8200.
-&lt;CAPIF_VAULT_TOKEN&gt;=Vault token to be used on request through vault. By default it is &quot;read-ca-token&quot;.
-&lt;MOCK_SERVER_URL&gt;=Setup Mock server url to be used in notifications at tests marked with mockserver tag. By default it is not set.
-
-To execute all tests run :
-docker run -ti --rm --network=&quot;host&quot; \
-    --add-host host.docker.internal:host-gateway \
-    --add-host vault:host-gateway \
-    --add-host register:host-gateway \
-    --add-host mock-server:host-gateway \
-    -v &lt;PATH_TO_REPOSITORY&gt;/tests:/opt/robot-tests/tests \
-    -v &lt;PATH_RESULT_FOLDER&gt;:/opt/robot-tests/results capif-robot-test:latest  \
-    --variable CAPIF_HOSTNAME:$CAPIF_HOSTNAME \
-    --variable CAPIF_HTTP_PORT:$CAPIF_HTTP_PORT \
-    --variable CAPIF_HTTPS_PORT:$CAPIF_HTTPS_PORT \
-    --variable CAPIF_REGISTER:$CAPIF_REGISTER \
-    --variable CAPIF_REGISTER_PORT:$CAPIF_REGISTER_PORT \
-    --variable CAPIF_VAULT:$CAPIF_VAULT \
-    --variable CAPIF_VAULT_PORT:$CAPIF_VAULT_PORT \
-    --variable CAPIF_VAULT_TOKEN:$CAPIF_VAULT_TOKEN \
-    --variable MOCK_SERVER_URL:$MOCK_SERVER_URL \
-    --include all
-</code></pre>
-<p>Execute specific tests locally:</p>
-<pre><code>To run more specific tests, for example, only one functionality:
-&lt;TAG&gt;=Select one from list:
-  &quot;capif_api_acl&quot;,
-  &quot;capif_api_auditing_service&quot;,
-  &quot;capif_api_discover_service&quot;,
-  &quot;capif_api_events&quot;,
-  &quot;capif_api_invoker_management&quot;,
-  &quot;capif_api_logging_service&quot;,
-  &quot;capif_api_provider_management&quot;,
-  &quot;capif_api_publish_service&quot;,
-  &quot;capif_security_api
-
-And Run:
-docker run -ti --rm --network=&quot;host&quot; \
-    --add-host host.docker.internal:host-gateway \
-    --add-host vault:host-gateway \
-    --add-host register:host-gateway \
-    --add-host mock-server:host-gateway \
-    -v &lt;PATH_TO_REPOSITORY&gt;/tests:/opt/robot-tests/tests \
-    -v &lt;PATH_RESULT_FOLDER&gt;:/opt/robot-tests/results capif-robot-test:latest  \
-    --variable CAPIF_HOSTNAME:$CAPIF_HOSTNAME \
-    --variable CAPIF_HTTP_PORT:$CAPIF_HTTP_PORT \
-    --variable CAPIF_HTTPS_PORT:$CAPIF_HTTPS_PORT \
-    --variable CAPIF_REGISTER:$CAPIF_REGISTER \
-    --variable CAPIF_REGISTER_PORT:$CAPIF_REGISTER_PORT \
-    --variable CAPIF_VAULT:$CAPIF_VAULT \
-    --variable CAPIF_VAULT_PORT:$CAPIF_VAULT_PORT \
-    --variable CAPIF_VAULT_TOKEN:$CAPIF_VAULT_TOKEN \
-    --variable MOCK_SERVER_URL:$MOCK_SERVER_URL \
-    --include &lt;TAG&gt;
-</code></pre>
-<h2 id="test-result-review">Test result review</h2>
-<p>In order to Review results after tests, you can check general report at <PATH_RESULT_FOLDER>/report.html or if you need more detailed information <PATH_RESULT_FOLDER>/log.html, example:</p>
-<ul>
-<li>
-<p>Report:
-<img alt="Report" src="robot_report_example.png" /></p>
-</li>
-<li>
-<p>Detailed information:
-<img alt="Log" src="robot_log_example.png" /></p>
-</li>
-</ul>
-<p><strong>NOTE: If you need more detail at Robot Framework Logs you can set log level option just adding to command --loglevel DEBUG</strong></p>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/robotframework/robot_log_example.png b/public/develop/testing/robotframework/robot_log_example.png
deleted file mode 100644
index 6c15a031e26eae47fed53b21a1e69e2f7bfa89db..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 158079
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
De;ua!

diff --git a/public/develop/testing/robotframework/robot_report_example.png b/public/develop/testing/robotframework/robot_report_example.png
deleted file mode 100644
index 1cf36d8766753d08938be73c87e958f4c8d56068..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 183065
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
Ee{B@pxc~qF

diff --git a/public/develop/testing/testplan/api_access_control_policy/index.html b/public/develop/testing/testplan/api_access_control_policy/index.html
deleted file mode 100644
index 46843fa..0000000
--- a/public/develop/testing/testplan/api_access_control_policy/index.html
+++ /dev/null
@@ -1,1441 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_access_control_policy/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Access Control Policy - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-access-control-policy" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Access Control Policy
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-access-control-policy">Test Plan for CAPIF Api Access Control Policy</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-retrieve-acl">Test Case 1: Retrieve ACL</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can retrieve ACL from CAPIF</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ol>
-<li>contain only one object.</li>
-<li>apiInvokerId must match apiInvokerId registered previously.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-2-retrieve-acl-with-2-service-apis-published">Test Case 2: Retrieve ACL with 2 Service APIs published</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can retrieve ACL from CAPIF for 2 different serviceApis published.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had two Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for both Service APIs published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong> and <strong>service_2</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information for <strong>service_1</strong>.</li>
-<li>Provider Get ACL information for <strong>service_2</strong>.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_2</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker for both published APIs</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL for <strong>serviceApiId1</strong></p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL for serviceApiId2</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId2}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ol>
-<li>contain one object.</li>
-<li>apiInvokerId must match apiInvokerId registered previously.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-3-retrieve-acl-with-security-context-created-by-two-different-invokers">Test Case 3: Retrieve ACL with security context created by two different Invokers</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can retrieve ACL from CAPIF containing 2 objects.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>Two API Invokers had a Security Context for same Service API published by provider.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong> and <strong>service_2</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker for both published APIs</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Repeat previous 3 steps in order to have a new Invoker.</p>
-</li>
-<li>
-<p>Provider Retrieve ACL for serviceApiId</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ol>
-<li>Contain two objects.</li>
-<li>One object must match with <strong>apiInvokerId1</strong> and the other one with <strong>apiInvokerId2</strong> an registered previously.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-4-retrieve-acl-filtered-by-api-invoker-id">Test Case 4: Retrieve ACL filtered by api-invoker-id</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can retrieve ACL filtering by apiInvokerId from CAPIF containing 1 objects.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>Two API Invokers had a Security Context for same Service API published by provider.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong> and <strong>service_2</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information with query parameter indicating first api-invoker-id.</li>
-<li>Provider Get ACL information with query parameter indicating second api-invoker-id.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker for both published APIs</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Repeat previous 3 steps in order to have a new Invoker.</p>
-</li>
-<li>
-<p>Provider Retrieve ACL for <strong>serviceApiId1</strong></p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={apiInvokerId1}</strong></li>
-<li>Use <strong>serviceApiId</strong>, <strong>aefId</strong> and <strong>apiInvokerId1</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL for <strong>serviceApiId2</strong></p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={apiInvokerId2}</strong></li>
-<li>Use <strong>serviceApiId</strong>, <strong>aefId</strong> and <strong>apiInvokerId2</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>ACL Response:</p>
-<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ol>
-<li>Contain one objects.</li>
-<li>Object must match with <strong>apiInvokerId1</strong>.</li>
-</ol>
-</li>
-</ol>
-</li>
-<li>
-<p>ACL Response:</p>
-<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ol>
-<li>Contain one objects.</li>
-<li>Object must match with <strong>apiInvokerId2</strong>.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-5-retrieve-acl-filtered-by-supported-features">Test Case 5: Retrieve ACL filtered by supported-features</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p><strong>CURRENTLY NOT SUPPORTED FEATURE</strong></p>
-<p>This test case will check that an API Provider can retrieve ACL filtering by supportedFeatures from CAPIF containing 1 objects.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>Two API Invokers had a Security Context for same Service API published by provider.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong> and <strong>service_2</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information with query parameter indicating first supported-features.</li>
-<li>Provider Get ACL information with query parameter indicating second supported-features.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker for both published APIs</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Repeat previous 3 steps in order to have a new Invoker.</p>
-</li>
-<li>
-<p>Provider Retrieve ACL for serviceApiId</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&amp;supported-features={apiInvokerId1}</strong></li>
-<li>Use <strong>serviceApiId</strong>, <strong>aefId</strong> and <strong>apiInvokerId1</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL for serviceApiId</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&amp;supported-features={apiInvokerId2}</strong></li>
-<li>Use <strong>serviceApiId</strong>, <strong>aefId</strong> and <strong>apiInvokerId2</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>ACL Response:</p>
-<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ol>
-<li>Contain one objects.</li>
-<li>Object must match with supportedFeatures1.</li>
-</ol>
-</li>
-</ol>
-</li>
-<li>
-<p>ACL Response:</p>
-<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ol>
-<li>Contain one objects.</li>
-<li>Object must match with supportedFeatures1.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-6-retrieve-acl-with-aef-id-not-valid">Test Case 6: Retrieve ACL with aef-id not valid</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-6</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can't retrieve ACL from CAPIF if aef-id is not valid</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${AEF_ID_NOT_VALID}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>AEF_ID_NOT_VALID</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>404 Not Found</strong> Response.</li>
-<li>body returned must accomplish <strong>Problem Details</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}".</li>
-<li>cause with message "Wrong id".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-7-retrieve-acl-with-service-id-not-valid">Test Case 7: Retrieve ACL with service-id not valid</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-7</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id is not valid</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>NOT_VALID_SERVICE_API_ID</strong> and <strong>aef_id</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>404 Not Found</strong> Response.</li>
-<li>body returned must accomplish <strong>Problem Details</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}".</li>
-<li>cause with message "Wrong id".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-8-retrieve-acl-with-service-api-id-and-aef-id-not-valid">Test Case 8: Retrieve ACL with service-api-id and aef-id not valid</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-8</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id and aef-id are not valid</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${AEF_ID_NOT_VALID}</strong></li>
-<li>Use <strong>NOT_VALID_SERVICE_API_ID</strong> and <strong>aef_id</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>404 Not Found</strong> Response.</li>
-<li>body returned must accomplish <strong>Problem Details</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}".</li>
-<li>cause with message "Wrong id".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-9-retrieve-acl-without-securitycontext-created-previously-by-invoker">Test Case 9: Retrieve ACL without SecurityContext created previously by Invoker</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-9</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can't retrieve ACL if no invoker had requested Security Context to CAPIF</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker created but no Security Context for Service API published had been requested.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>
-<p>Discover published APIs</p>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>404 Not Found</strong> Response.</li>
-<li>body returned must accomplish <strong>Problem Details</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}".</li>
-<li>cause with message "Wrong id".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-10-retrieve-acl-filtered-by-api-invoker-id-not-present">Test Case 10: Retrieve ACL filtered by api-invoker-id not present</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-10</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider get not found response if filter by not valid api-invoker-id doesn't match any registered ACL.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={NOT_VALID_API_INVOKER_ID}</strong></li>
-<li>Use <strong>serviceApiId</strong>, <strong>aefId</strong> and <strong>NOT_VALID_API_INVOKER_ID</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>404 Not Found</strong> Response.</li>
-<li>body returned must accomplish <strong>Problem Details</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}".</li>
-<li>cause with message "Wrong id".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-11-retrieve-acl-with-apf-certificate">Test Case 11: Retrieve ACL with APF Certificate</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-11</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can't retrieve ACL from CAPIF using <strong>APF Certificate</strong></p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use APF Provider Certificate</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 401</li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "Certificate not authorized".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-12-retrieve-acl-with-amf-certificate">Test Case 12: Retrieve ACL with AMF Certificate</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-12</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can't retrieve ACL from CAPIF using AMF Certificate</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use AMF Provider Certificate</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 401</li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "Certificate not authorized".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-13-retrieve-acl-with-invoker-certificate">Test Case 13: Retrieve ACL with Invoker Certificate</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-13</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Provider can't retrieve ACL from CAPIF using <strong>Invoker Certificate</strong></p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 401</li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "Certificate not authorized".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-14-no-acl-for-invoker-after-be-removed">Test Case 14: No ACL for invoker after be removed</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_acl-14</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that ACLs are removed after invoker is removed.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for Service API published and ACL is present</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong></li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Provider Get ACL information of invoker.</li>
-<li>Remove Invoker from CAPIF.</li>
-<li>Provider Get ACL information of invoker.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> store apiInvokerId</p>
-</li>
-<li>Discover published APIs</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Provider Retrieve ACL</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={api-invoker-id}</strong></li>
-<li>Use <strong>serviceApiId</strong>, <strong>aefId</strong> and <strong>api-invoker-id</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-<li>Remove Invoker from CAPIF</li>
-<li>Provider Retrieve ACL<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&amp;api-invoker-id={api-invoker-id}</strong></li>
-<li>Use <strong>serviceApiId</strong>, <strong>aefId</strong> and <strong>api-invoker-id</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:
-  1. ACL Response:
-     1. <strong>200 OK</strong> Response.
-     2. body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.
-     3. <strong>apiInvokerPolicies</strong> must:
-        1. contain only one object.
-        2. apiInvokerId must match apiInvokerId registered previously.</p>
-<ol>
-<li>ACL Response:<ol>
-<li><strong>404 Not Found</strong> Response.</li>
-<li>body returned must accomplish <strong>Problem Details</strong> data structure.</li>
-<li><strong>apiInvokerPolicies</strong> must:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: None and supportedFeatures: None".</li>
-<li>cause with message "Wrong id".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_access_control_policy/service_api_description_post_example.json b/public/develop/testing/testplan/api_access_control_policy/service_api_description_post_example.json
deleted file mode 100644
index b725b42..0000000
--- a/public/develop/testing/testplan/api_access_control_policy/service_api_description_post_example.json
+++ /dev/null
@@ -1,113 +0,0 @@
-{
-  "apiName": "service_1",
-  "aefProfiles": [
-    {
-      "aefId": "string",
-      "versions": [
-        {
-          "apiVersion": "v1",
-          "expiry": "2021-11-30T10:32:02.004Z",
-          "resources": [
-            {
-              "resourceName": "string",
-              "commType": "REQUEST_RESPONSE",
-              "uri": "string",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ],
-          "custOperations": [
-            {
-              "commType": "REQUEST_RESPONSE",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ]
-        }
-      ],
-      "protocol": "HTTP_1_1",
-      "dataFormat": "JSON",
-      "securityMethods": ["PSK"],
-      "interfaceDescriptions": [
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        },
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        }
-      ]
-    },
-    {
-      "aefId": "string",
-      "versions": [
-        {
-          "apiVersion": "v1",
-          "expiry": "2021-11-30T10:32:02.004Z",
-          "resources": [
-            {
-              "resourceName": "string",
-              "commType": "REQUEST_RESPONSE",
-              "uri": "string",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ],
-          "custOperations": [
-            {
-              "commType": "REQUEST_RESPONSE",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ]
-        }
-      ],
-      "protocol": "HTTP_1_1",
-      "dataFormat": "JSON",
-      "securityMethods": ["PSK"],
-      "interfaceDescriptions": [
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        },
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        }
-      ]
-    }
-  ],
-  "description": "string",
-  "supportedFeatures": "fffff",
-  "shareableInfo": {
-    "isShareable": true,
-    "capifProvDoms": [
-      "string"
-    ]
-  },
-  "serviceAPICategory": "string",
-  "apiSuppFeats": "fffff",
-  "pubApiPath": {
-    "ccfIds": [
-      "string"
-    ]
-  },
-  "ccfId": "string"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_auditing_service/index.html b/public/develop/testing/testplan/api_auditing_service/index.html
deleted file mode 100644
index ff01742..0000000
--- a/public/develop/testing/testplan/api_auditing_service/index.html
+++ /dev/null
@@ -1,700 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_auditing_service/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Auditing Service - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-auditing-service" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Auditing Service
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-auditing-service">Test Plan for CAPIF Api Auditing Service</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-get-capif-log-entry">Test Case 1: Get CAPIF Log Entry.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_auditing-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF AMF can get log entry to Logging Service</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-<li>Log Entry exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry
-  4. Get Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a>, <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a> </p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Log Entry:</p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body <a href="../api_logging_service/invocation_log.json" title="Log Request Body">log entry request body</a></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Get Log:</p>
-<ol>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}</strong></li>
-<li>Use <strong>AMF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>200 OK</strong></li>
-<li>Response Body must follow <strong>InvocationLog</strong> data structure with:<ul>
-<li>aefId</li>
-<li>apiInvokerId</li>
-<li>logs</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-2-get-capif-log-entry-with-no-log-entry-in-capif">Test Case 2: Get CAPIF Log Entry With no Log entry in CAPIF.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_auditing-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF AEF can create log entry to Logging Service</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Get Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a>, <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a> </p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Get Log:</p>
-<ol>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}</strong></li>
-<li>Use <strong>AMF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found Log Entry in CAPIF".</li>
-<li>cause with message "Not Exist Logs with the filters applied".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-3-get-capif-log-entry-without-aef-id-and-api-invoker-id">Test Case 3: Get CAPIF Log Entry without aef-id and api-invoker-id.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_auditing-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF AEF can create log entry to Logging Service</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is no pre-authorised (has no valid AMF cert from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-<li>Log Entry exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry
-  4. Get Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a>, <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a> </p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Log Entry:</p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body <a href="../api_logging_service/invocation_log.json" title="Log Request Body">log entry request body</a></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Get Log:</p>
-<ol>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs</strong></li>
-<li>Use <strong>AMF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>400 Bad Request</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 400</li>
-<li>title with message "Bad Request"</li>
-<li>detail with message "aef_id and api_invoker_id parameters are mandatory".</li>
-<li>cause with message "Mandatory parameters missing".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-4-get-capif-log-entry-with-filtter-api-version">Test Case 4: Get CAPIF Log Entry with filtter api-version.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_auditing-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF AMF can get log entry to Logging Service</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-<li>Log Entry exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry
-  4. Get Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a>, <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a> </p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Log Entry:</p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body <a href="../api_logging_service/invocation_log.json" title="Log Request Body">log entry request body</a></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Get Log:</p>
-<ol>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}&amp;api-version={v1}</strong></li>
-<li>Use <strong>AMF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>200 OK</strong></li>
-<li>Response Body must follow <strong>InvocationLog</strong> data structure with:<ul>
-<li>aefId</li>
-<li>apiInvokerId</li>
-<li>logs</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-5-get-capif-log-entry-with-filter-api-version-but-not-exist-in-log-entry">Test Case 5: Get CAPIF Log Entry with filter api-version but not exist in log entry.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_auditing-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF AMF can get log entry to Logging Service</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-<li>Log Entry exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry
-  4. Get Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a>, <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a> </p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Log Entry:</p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body <a href="../api_logging_service/invocation_log.json" title="Log Request Body">log entry request body</a></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Get Log:</p>
-<ol>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&amp;api-invoker-id={api-invoker-id}&amp;api-version={v58}</strong></li>
-<li>Use <strong>AMF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>detail with message "Parameters do not match any log entry"</li>
-<li>cause with message "No logs found".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_discover_service/index.html b/public/develop/testing/testplan/api_discover_service/index.html
deleted file mode 100644
index 4b77df1..0000000
--- a/public/develop/testing/testplan/api_discover_service/index.html
+++ /dev/null
@@ -1,857 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_discover_service/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Discover Service - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-discover-service" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Discover Service
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-discover-service">Test Plan for CAPIF Discover Service</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-discover-published-service-apis-by-authorised-api-invoker">Test Case 1: Discover Published service APIs by Authorised API Invoker</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_discover_service-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check if Network App (Invoker) can discover published service APIs.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Service APIs are published.</li>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously with {onboardingId}</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Request Discover Published APIs:<ul>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>Response to Discover Request By Invoker:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>Response body must follow <strong>DiscoveredAPIs</strong> data structure:<ul>
-<li>Check if DiscoveredAPIs contains the API Published previously</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-2-discover-published-service-apis-by-non-authorised-api-invoker">Test Case 2: Discover Published service APIs by Non Authorised API Invoker</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_discover_service-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher can't discover published APIs because is not authorized.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Service APIs are published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover Service APIs by no invoker entity</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Request Discover Published APIs by no invoker entity:<ul>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Use not <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Discover Request By no invoker entity:</p>
-<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 401</li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "User not authorized".</li>
-<li>cause with message "Certificate not authorized".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-3-discover-published-service-apis-by-not-registered-api-invoker">Test Case 3: Discover Published service APIs by not registered API Invoker</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_discover_service-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a not registered invoker is forbidden to discover published APIs.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Service APIs are published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover Service APIs by Publisher</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Request Discover Published APIs with not valid apiInvoker:<ul>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={INVOKER_NOT_REGISTERED}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Discover Request By Invoker:</p>
-<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "API Invoker does not exist".</li>
-<li>cause with message "API Invoker id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-4-discover-published-service-apis-by-registered-api-invoker-with-1-result-filtered">Test Case 4: Discover Published service APIs by registered API Invoker with 1 result filtered</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_discover_service-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check if Network App (Invoker) can discover published service APIs.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>At least 2 Service APIs are published.</li>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously with {onboardingId}</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> and <strong>service_2</strong> at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Discover filtered by api-name <strong>service_1</strong> Service APIs by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_2</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Request Discover Published APIs filtering by api-name:<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&amp;api-name=</strong>service_1**</li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-<li>filter by api-name <strong>service_1</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Publish request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>Response to Discover Request By Invoker:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>Response body must follow <strong>DiscoveredAPIs</strong> data structure:<ul>
-<li>Check if DiscoveredAPIs contains previously registered Service APIs published.</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>Response to Discover Request By Invoker:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>Response body must follow <strong>DiscoveredAPIs</strong> data structure:<ul>
-<li>Check if DiscoveredAPIs contains only Service API published with api-name <strong>service_1</strong></li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-5-discover-published-service-apis-by-registered-api-invoker-filtered-with-no-match">Test Case 5: Discover Published service APIs by registered API Invoker filtered with no match</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_discover_service-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check if Network App (Invoker) can discover published service APIs.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>At least 2 Service APIs are published.</li>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously with {onboardingId}</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> and <strong>service_2</strong> at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Discover filtered by api-name not published Service APIs by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_2</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Request Discover Published APIs filtering by api-name not published:<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&amp;api-name=NOT_VALID_NAME</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-<li>filter by api-name NOT_VALID_NAME</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Publish request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>Response to Discover Request By Invoker:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>Response body must follow <strong>DiscoveredAPIs</strong> data structure:<ul>
-<li>Check if DiscoveredAPIs contains previously registered Service APIs published.</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>Response to Discover Request By Invoker:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "API Invoker {api_invoker_id} has no API Published that accomplish filter conditions".</li>
-<li>cause with message "No API Published accomplish filter conditions".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-6-discover-published-service-apis-by-registered-api-invoker-not-filtered">Test Case 6: Discover Published service APIs by registered API Invoker not filtered</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_discover_service-6</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check if Network App (Invoker) can discover published service APIs.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>2 Service APIs are published.</li>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously with {onboardingId}</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> and <strong>service_2</strong> at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Discover without filter by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="../api_publish_service/service_api_description_post_example.json" title="Service API **Description** Request">service api description</a> with apiName <strong>service_2</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Request Discover Published APIs not filtered:<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Discover Request By Invoker:</p>
-<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>Response body must follow <strong>DiscoveredAPIs</strong> data structure:<ul>
-<li>Check if DiscoveredAPIs contains the 2 previously registered Service APIs published.</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_events_service/event_subscription.json b/public/develop/testing/testplan/api_events_service/event_subscription.json
deleted file mode 100644
index 40dc09b..0000000
--- a/public/develop/testing/testplan/api_events_service/event_subscription.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-  "eventFilters": [
-    {
-      "aefIds": ["aefIds", "aefIds"],
-      "apiIds": ["apiIds", "apiIds"],
-      "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"]
-    },
-    {
-      "aefIds": ["aefIds", "aefIds"],
-      "apiIds": ["apiIds", "apiIds"],
-      "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"]
-    }
-  ],
-  "eventReq": {
-    "grpRepTime": 5,
-    "immRep": true,
-    "maxReportNbr": 0,
-    "monDur": "2000-01-23T04:56:07+00:00",
-    "partitionCriteria": ["string1", "string2"],
-    "repPeriod": 6,
-    "sampRatio": 15
-  },
-  "events": ["SERVICE_API_AVAILABLE", "API_INVOKER_ONBOARDED"],
-  "notificationDestination": "http://robot.testing",
-  "requestTestNotification": true,
-  "supportedFeatures": "aaa",
-  "websockNotifConfig": {
-    "requestWebsocketUri": true,
-    "websocketUri": "websocketUri"
-  }
-}
diff --git a/public/develop/testing/testplan/api_events_service/index.html b/public/develop/testing/testplan/api_events_service/index.html
deleted file mode 100644
index db93d39..0000000
--- a/public/develop/testing/testplan/api_events_service/index.html
+++ /dev/null
@@ -1,1375 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_events_service/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Events Service - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-events-service" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Events Service
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-events-service">Test Plan for CAPIF Api Events Service</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<hr />
-<h2 id="test-case-1-creates-a-new-individual-capif-event-subscription">Test Case 1: Creates a new individual CAPIF Event Subscription.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (Invoker or Publisher) can Subscribe to Events</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Subscribe to Events</li>
-<li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Event Subscription:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Event Subscription must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>
-<p>Event Subscriptions are stored in CAPIF Database</p>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-2-creates-a-new-individual-capif-event-subscription-with-invalid-subscriberid">Test Case 2: Creates a new individual CAPIF Event Subscription with Invalid SubscriberId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Subscribe to Events without valid SubcriberId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is not pre-authorised (has invalid InvokerId or apfId)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Subscribe to Events</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Event Subscription:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_NOT_REGISTERED}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Event Subscription must accomplish:</p>
-<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker or APF or AEF or AMF Not found".</li>
-<li>cause with message "Subscriber Not Found".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Event Subscriptions are not stored in CAPIF Database</p>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-3-deletes-an-individual-capif-event-subscription">Test Case 3: Deletes an individual CAPIF Event Subscription</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (Invoker or Publisher) can Delete an Event Subscription</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Subscribe to Events</li>
-<li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li>
-<li>Remove Event Subscription</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Event Subscription:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>
-<p>Remove Event Subscription:</p>
-<ol>
-<li>Send <strong>DELETE</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Event Subscription must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>
-<p>Event Subscriptions are stored in CAPIF Database</p>
-</li>
-<li>
-<p>Remove Event Subscription:</p>
-<ol>
-<li><strong>204 No Content</strong></li>
-</ol>
-</li>
-<li>
-<p>Event Subscription is not present at CAPIF Database.</p>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-4-deletes-an-individual-capif-event-subscription-with-invalid-subscriberid">Test Case 4: Deletes an individual CAPIF Event Subscription with invalid SubscriberId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete to Events without valid SubcriberId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId).</li>
-<li>CAPIF subscriber is subscribed to Events.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Subscribe to Events</li>
-<li>Retrieve Location Header with subscriptionId.</li>
-<li>Remove Event Subscribed with not valid Subscriber.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Event Subscription:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>
-<p>Remove Event Subcription with not valid subscriber:</p>
-<ol>
-<li>Send <strong>DELETE</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_ID_NOT_VALID}/subscriptions/{subcriptionId}</strong></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Event Subscription must accomplish:</p>
-<ol>
-<li>201 Created</li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>
-<p>Event Subscriptions are stored in CAPIF Database</p>
-</li>
-<li>
-<p>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:</p>
-<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker or APF or AEF or AMF Not found".</li>
-<li>cause with message "Subscriber Not Found".</li>
-</ul>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-5-deletes-an-individual-capif-event-subscription-with-invalid-subscriptionid">Test Case 5: Deletes an individual CAPIF Event Subscription with invalid SubscriptionId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete an Event Subscription without valid SubscriptionId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has invalid InvokerId or apfId).</li>
-<li>CAPIF subscriber is subscribed to Events.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Subscribe to Events</li>
-<li>Retrieve Location Header with subscriptionId.</li>
-<li>Remove Event Subscribed with not valid Subscriber.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Event Subscription:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>
-<p>Remove Event Subcription with not valid subscriber:</p>
-<ol>
-<li>Send <strong>DELETE</strong> to to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subcriberId}/subscriptions/{SUBSCRIPTION_ID_NOT_VALID}</strong></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Event Subscription must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>
-<p>Event Subscriptions are stored in CAPIF Database</p>
-</li>
-<li>Remove Event Subscription with not valid subscriber:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>detail with message "Service API not existing".</li>
-<li>cause with message "Event API subscription id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-6-invoker-receives-service-api-invocation-events">Test Case 6: Invoker receives Service API Invocation events</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-6</em></strong>, <strong><em>mockserver</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF Invoker subscribed to SERVICE_API_INVOCATION_SUCCESS and SERVICE_API_INVOCATION_FAILURE, receive the notification when AEF Send <strong>TO</strong> logging service result of invocations to their APIs.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-<li>CAPIF provider is correctly registered and published APIs.</li>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li><strong>Mock Server is up and running to receive requests.</strong></li>
-<li><strong>Mock Server is clean.</strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register provider and publish one API at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover published APIs and extract apiIds and apiNames</li>
-<li>Subscribe to <strong>SERVICE_API_INVOCATION_SUCCESS</strong> and <strong>SERVICE_API_INVOCATION_FAILURE</strong> event filtering by aefId.</li>
-<li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li>
-<li>Emulate Success and Failure on API invocation of provider by Invoker, using Invocation Logs API.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">provider registration</a></li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Discover published APIs:</p>
-<ul>
-<li>Get <strong>Api Ids</strong> And <strong>Api Names</strong> from response.</li>
-</ul>
-</li>
-<li>
-<p>Event Subscription to SERVICE_API_INVOCATION_SUCCESS and SERVICE_API_INVOCATION_FAILURE of provider previously registered:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a> with:<ol>
-<li>events: <strong>['SERVICE_API_INVOCATION_SUCCESS','SERVICE_API_INVOCATION_FAILURE']</strong></li>
-<li>eventFilter: only receive events from provider's aefId.</li>
-</ol>
-</li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>
-<p>Create Log Entry emulating provider receive Success and Failure api invocation from invoker:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body <a href="../api_logging_service/invocation_log.json" title="Log Request Body">log entry request body</a> with:<ol>
-<li>aefId from provider published.</li>
-<li>apiInvokerId from invoker onboarded.</li>
-<li>apiId of published API</li>
-<li>apiName of published API</li>
-<li>200 and 400 results in two logs.</li>
-</ol>
-</li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Event Subscription must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>Response to creation of log entry on CCF must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/api-invocation-logs/{apiVersion}/{aefId}/subscriptions/{logId}</strong></li>
-</ol>
-</li>
-<li>Mock Server received messages must accomplish:<ol>
-<li><strong>Two Events have been received</strong>.</li>
-<li>Validate received events follow <strong>EventNotification</strong> data structure, with <strong>invocationLog</strong> in <strong>eventDetail</strong> parameter.<ol>
-<li>One should be <strong>SERVICE_API_INVOCATION_SUCCESS</strong> related with <strong>200</strong> result at Log.</li>
-<li>The other one must be <strong>SERVICE_API_INVOCATION_FAILURE</strong> related with <strong>400</strong> result at Log.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-7-invoker-subscribe-to-service-api-available-and-unavailable-events">Test Case 7: Invoker subscribe to Service API Available and Unavailable events</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-7</em></strong>, <strong><em>mockserver</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF Invoker subscribed to SERVICE_API_AVAILABLE and SERVICE_API_UNAVAILABLE, receive the notification when AEF publish and remove it. </p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-<li>CAPIF provider is correctly registered and published APIs.</li>
-<li><strong>Mock Server is up and running to receive requests.</strong></li>
-<li><strong>Mock Server is clean.</strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register provider and publish one API at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover published APIs and extract apiIds and apiNames</li>
-<li>Subscribe to <strong>SERVICE_API_AVAILABLE</strong> and <strong>SERVICE_API_UNAVAILABLE</strong> event filtering by aefId.</li>
-<li>Retrieve {subscriberId} and {subscriptionId} from Location Header</li>
-<li>Provider publish new API.</li>
-<li>Provider remove published API.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">provider registration</a></li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Discover published APIs:</p>
-<ul>
-<li>Get <strong>Api Ids</strong> And <strong>Api Names</strong> from response.</li>
-</ul>
-</li>
-<li>
-<p>Event Subscription to SERVICE_API_AVAILABLE and SERVICE_API_UNAVAILABLE of provider previously registered:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a> with:<ol>
-<li>events: <strong>['SERVICE_API_AVAILABLE','SERVICE_API_UNAVAILABLE']</strong></li>
-<li>eventFilter: only receive events from provider's aefId.</li>
-</ol>
-</li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>
-<p>Publish new Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_2</strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Remove published Service API at CCF:</p>
-<ul>
-<li>Send <strong>DELETE</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID}</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Event Subscription must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>
-<p>Mock Server received messages must accomplish:</p>
-<ol>
-<li><strong>Two Events have been received</strong>.</li>
-<li>Validate received events follow <strong>EventNotification</strong> data structure, with <strong>apiIds</strong> in <strong>eventDetail</strong> parameter.<ol>
-<li>One should be <strong>SERVICE_API_AVAILABLE</strong> apiId of <strong>service_2</strong> published API.</li>
-<li>The other one must be <strong>SERVICE_API_UNAVAILABLE</strong> apiId of <strong>service_1</strong> published API.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-8-invoker-subscribe-to-service-api-update">Test Case 8: Invoker subscribe to Service API Update</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-8</em></strong>, <strong><em>mockserver</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF Invoker subscribed to SERVICE_API_UPDATE, receive the notification when AEF Update some information on API Published.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-<li>CAPIF provider is correctly registered and published APIs.</li>
-<li>API Provider had a Service API Published on CAPIF</li>
-<li><strong>Mock Server is up and running to receive requests.</strong></li>
-<li><strong>Mock Server is clean.</strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider and publish one API at CCF</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Discover published APIs and extract apiIds and apiNames</li>
-<li>Subscribe to <strong>SERVICE_API_UPDATE</strong> event filtering by aefId.</li>
-<li>Retrieve {subscriberId} and {subscriptionId} from Location Header at event subscription</li>
-<li>Provider update information of Service API Published.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Check and Clean Mock Server</li>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">provider registration</a></li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong><em>APF Certificate</em></strong></li>
-<li>Store <strong>serviceApiId</strong></li>
-</ul>
-</li>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Discover published APIs:</p>
-<ul>
-<li>Get <strong>Api Ids</strong> And <strong>Api Names</strong> from response.</li>
-</ul>
-</li>
-<li>
-<p>Event Subscription to SERVICE_API_UPDATE of provider previously registered:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a> with:<ol>
-<li>events: <strong>['SERVICE_API_UPDATE']</strong></li>
-<li>eventFilter: only receive events from provider's aefId.</li>
-</ol>
-</li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>
-<p>Update published API at CCF:</p>
-<ul>
-<li>Send <strong>PUT</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</strong></li>
-<li>body [service api description] with overrided <strong>apiName</strong> to <strong>service_1</strong>_modified**</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Event Subscription must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>Response to Update Published Service API:<ol>
-<li><strong>200 OK</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiName <strong>service_1</strong>_modified**</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>Mock Server received messages must accomplish:<ol>
-<li><strong>One Event has been received</strong>.</li>
-<li>Validate received events follow <strong>EventNotification</strong> data structure, with <strong>serviceAPIDescriptions</strong> in <strong>eventDetail</strong> parameter.<ol>
-<li>Event should be <strong>SERVICE_API_UPDATE</strong> with <strong>eventDetail</strong> with modified <strong>apiName</strong>.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-9-provider-subscribe-to-api-invoker-events">Test Case 9: Provider subscribe to API Invoker events</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-9</em></strong>, <strong><em>mockserver</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF Provider subscribed to API Invoker events (API_INVOKER_ONBOARDED, API_INVOKER_UPDATED and API_INVOKER_OFFBOARDED), receive the notifications when Invoker is onboarded, updated and removed respectively.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-<li>CAPIF provider is correctly registered.</li>
-<li><strong>Mock Server is up and running to receive requests.</strong></li>
-<li><strong>Mock Server is clean.</strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Subscribe Provider to <strong>API_INVOKER_ONBOARDED, API_INVOKER_UPDATED and API_INVOKER_OFFBOARDED</strong> events.</li>
-<li>Register Invoker and Onboard Invoker at CCF</li>
-<li>Update Onboarding Information at CCF with a minor change on "notificationDestination"</li>
-<li>Offboard Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Check and Clean Mock Server</li>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">provider registration</a></li>
-<li>Event Subscription to API_INVOKER_ONBOARDED, API_INVOKER_UPDATED and API_INVOKER_OFFBOARDED events:<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a> with:<ol>
-<li>events: <strong>['API_INVOKER_ONBOARDED', 'API_INVOKER_UPDATED', 'API_INVOKER_OFFBOARDED']</strong></li>
-</ol>
-</li>
-<li>Use <strong>Provider AMF Certificate</strong></li>
-</ol>
-</li>
-<li>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></li>
-<li>Update information of previously onboarded Invoker:<ul>
-<li>Send <strong>PUT</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</strong></li>
-<li>Reference Request Body is: [put invoker onboarding body]</li>
-<li>"notificationDestination": "<strong>http://host.docker.internal:8086/netapp_new_callback</strong>",</li>
-</ul>
-</li>
-<li>Offboard:<ul>
-<li>Send <strong>DELETE</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Event Subscription must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>Response to Update Request (PUT) with minor change must contain:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>notificationDestination on response must contain the new value</li>
-</ol>
-</li>
-<li>Response to Offboard Request (DELETE) must contain:<ol>
-<li><strong>204 No Content</strong></li>
-</ol>
-</li>
-<li>Mock Server received messages must accomplish:<ol>
-<li><strong>Three Events have been received</strong>.</li>
-<li>Validate received events follow <strong>EventNotification</strong> data structure, with <strong>apiInvokerIds</strong> in <strong>eventDetail</strong> parameter.<ol>
-<li>One Event should be <strong>API_INVOKER_ONBOARDED</strong> with <strong>eventDetail</strong> with modified <strong>apiInvokerId</strong>.</li>
-<li>One Event should be <strong>API_INVOKER_UPDATED</strong> with <strong>eventDetail</strong> with modified <strong>apiInvokerId</strong>.</li>
-<li>One Event should be <strong>API_INVOKER_OFFBOARDED</strong> with <strong>eventDetail</strong> with modified <strong>apiInvokerId</strong>.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-10-provider-subscribed-to-acl-update-event">Test Case 10: Provider subscribed to ACL update event</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-10</em></strong>, <strong><em>mockserver</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF Provider subscribed to ACCESS_CONTROL_POLICY_UPDATE receive a notification when ACL Changes.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-<li>CAPIF provider is correctly registered.</li>
-<li>API Provider had one Service API Published on CAPIF</li>
-<li>API Invoker had a Security Context for the Service API published by provider.</li>
-<li><strong>Mock Server is up and running to receive requests.</strong></li>
-<li><strong>Mock Server is clean.</strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong>.</li>
-<li>Register Invoker and Onboard Invoker at CCF.</li>
-<li>Subscribe Provider to <strong>ACCESS_CONTROL_POLICY_UPDATE</strong> event.</li>
-<li>Discover APIs filtered by <strong>aef_id</strong></li>
-<li>Create Security Context for Invoker.</li>
-<li>Provider Retrieve ACL</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Check and Clean Mock Server</li>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">provider registration</a></li>
-<li>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></li>
-<li>Event Subscription to <strong>ACCESS_CONTROL_POLICY_UPDATE</strong> event:<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a> with:<ol>
-<li>events: <strong>['ACCESS_CONTROL_POLICY_UPDATE']</strong></li>
-<li>eventFilters: apiInvokerIds array with apiInvokerId of invoker</li>
-</ol>
-</li>
-<li>Use <strong>Provider AMF Certificate</strong></li>
-</ol>
-</li>
-<li>Discover published APIs</li>
-<li>Create Security Context for Invoker<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>Provider Retrieve ACL<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use AEF Provider Certificate</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Event Subscription must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>Create security context:<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</strong></li>
-</ol>
-</li>
-<li>ACL Response:<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li>apiInvokerPolicies must:<ol>
-<li>contain only one object.</li>
-<li>apiInvokerId must match apiInvokerId registered previously.</li>
-</ol>
-</li>
-</ol>
-</li>
-<li>Mock Server received messages must accomplish:<ol>
-<li><strong>One Event has been received</strong>.</li>
-<li>Validate received event follow <strong>EventNotification</strong> data structure, with <strong>accCtrlPolListExt</strong> in <strong>eventDetail</strong> parameter.<ol>
-<li>One Event should be <strong>ACCESS_CONTROL_POLICY_UPDATE</strong> with <strong>eventDetail</strong> with <strong>accCtrlPolListExt</strong> including the <strong>apiId</strong> and <strong>apiInvokerPolicies</strong>.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-11-provider-receives-an-acl-unavailable-event-when-invoker-remove-security-context">Test Case 11: Provider receives an ACL unavailable event when invoker remove Security Context.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-11</em></strong>, <strong><em>mockserver</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF Invoker subscribed to ACCESS_CONTROL_POLICY_UNAVAILABLE will receive the notification when AEF remove Security Context created previously.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-<li>CAPIF provider is correctly registered.</li>
-<li>API Provider had one Service API Published on CAPIF</li>
-<li><strong>Mock Server is up and running to receive requests.</strong></li>
-<li><strong>Mock Server is clean.</strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong>.</li>
-<li>Register Invoker and Onboard Invoker at CCF.</li>
-<li>Subscribe Invoker to <strong>ACCESS_CONTROL_POLICY_UNAVAILABLE</strong> event.</li>
-<li>Discover APIs filtered by <strong>aef_id</strong></li>
-<li>Create Security Context for Invoker.</li>
-<li>Provider Retrieve ACL.</li>
-<li>Remove Security Context for Invoker.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Check and Clean Mock Server</li>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">provider registration</a></li>
-<li>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></li>
-<li>Event Subscription to <strong>ACCESS_CONTROL_POLICY_UNAVAILABLE</strong> event:<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a> with:<ol>
-<li>events: <strong>['ACCESS_CONTROL_POLICY_UNAVAILABLE']</strong></li>
-<li>eventFilters: apiInvokerIds array with apiInvokerId of invoker</li>
-</ol>
-</li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>Discover published APIs</li>
-<li>Create Security Context for Invoker<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>Provider Retrieve ACL<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}</strong></li>
-<li>Use <strong>serviceApiId</strong> and <strong>aefId</strong></li>
-<li>Use <strong>AEF Provider Certificate</strong></li>
-</ul>
-</li>
-<li>Delete Security Context of Invoker by Provider:<ul>
-<li>Send <strong>DELETE</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Event Subscription must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>Create security context:<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</strong></li>
-</ol>
-</li>
-<li>ACL Response:<ol>
-<li><strong>200 OK</strong> Response.</li>
-<li>body returned must accomplish <strong>AccessControlPolicyList</strong> data structure.</li>
-<li>apiInvokerPolicies must:<ol>
-<li>contain only one object.</li>
-<li>apiInvokerId must match apiInvokerId registered previously.</li>
-</ol>
-</li>
-</ol>
-</li>
-<li>Delete security context:<ol>
-<li><strong>204 No Content</strong> response.</li>
-</ol>
-</li>
-<li>Mock Server received messages must accomplish:<ol>
-<li><strong>One Event has been received</strong>.</li>
-<li>Validate received event follow <strong>EventNotification</strong> data structure, without <strong>eventDetail</strong> parameter.<ol>
-<li>One Event should be <strong>ACCESS_CONTROL_POLICY_UNAVAILABLE</strong> without <strong>eventDetail</strong>.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-<h2 id="test-case-12-invoker-receives-an-invoker-authorization-revoked-and-acl-unavailable-event-when-provider-revoke-invoker-authorization">Test Case 12: Invoker receives an Invoker Authorization Revoked and ACL unavailable event when Provider revoke Invoker Authorization.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_events-12</em></strong>, <strong><em>mockserver</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF Invoker subscribed to API_INVOKER_AUTHORIZATION_REVOKED and ACCESS_CONTROL_POLICY_UNAVAILABLE receive both notification when AEF revoke invoker's authorization.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority)</li>
-<li>CAPIF provider is correctly registered.</li>
-<li>API Provider had one Service API Published on CAPIF</li>
-<li><strong>Mock Server is up and running to receive requests.</strong></li>
-<li><strong>Mock Server is clean.</strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF.</li>
-<li>Publish a provider API with name <strong>service_1</strong>.</li>
-<li>Register Invoker and Onboard Invoker at CCF.</li>
-<li>Subscribe Invoker to <strong>ACCESS_CONTROL_POLICY_UNAVAILABLE and API_INVOKER_AUTHORIZATION_REVOKED</strong> events.</li>
-<li>Discover APIs filtered by <strong>aef_id</strong></li>
-<li>Create Security Context for Invoker.</li>
-<li>Revoke Authorization by Provider.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Check and Clean Mock Server</li>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">provider registration</a></li>
-<li>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></li>
-<li>Event Subscription to <strong>ACCESS_CONTROL_POLICY_UNAVAILABLE and API_INVOKER_AUTHORIZATION_REVOKED</strong> event:<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions</strong></li>
-<li>body <a href="event_subscription.json" title="Event Subscription Request">event subscription request body</a> with:<ol>
-<li>events: <strong>['ACCESS_CONTROL_POLICY_UNAVAILABLE','API_INVOKER_AUTHORIZATION_REVOKED']</strong></li>
-<li>eventFilters: apiInvokerIds array with apiInvokerId of invoker</li>
-</ol>
-</li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ol>
-</li>
-<li>Discover published APIs</li>
-<li>Create Security Context for Invoker<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="../api_security_service/service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>Revoke Authorization by Provider:<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete</strong></li>
-<li>body <a href="./security_notification.json" title="Security Notification Request">security notification body</a></li>
-<li>Using <strong>AEF Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Event Subscription must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: <strong>{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId}</strong></li>
-<li>Response Body must follow <strong>EventSubscription</strong> data structure.</li>
-</ol>
-</li>
-<li>Create security context:<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</strong></li>
-</ol>
-</li>
-<li>Revoke Authorization:<ol>
-<li><strong>204 No Content</strong> response.</li>
-</ol>
-</li>
-<li>Mock Server received messages must accomplish:<ol>
-<li><strong>Two Events has been received</strong>.</li>
-<li>Validate received event follow <strong>EventNotification</strong> data structure, without <strong>eventDetail</strong> parameter.<ol>
-<li>One Event should be <strong>ACCESS_CONTROL_POLICY_UNAVAILABLE</strong> without <strong>eventDetail</strong>.</li>
-<li>One Event should be <strong>API_INVOKER_AUTHORIZATION_REVOKED</strong> without <strong>eventDetail</strong>.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<hr />
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_invoker_management/index.html b/public/develop/testing/testplan/api_invoker_management/index.html
deleted file mode 100644
index 203d3fd..0000000
--- a/public/develop/testing/testplan/api_invoker_management/index.html
+++ /dev/null
@@ -1,765 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_invoker_management/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Invoker Management - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-invoker-management" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Invoker Management
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-invoker-management">Test Plan for CAPIF Api Invoker Management</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-onboard-network-app">Test Case 1: Onboard Network App</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_invoker_management-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test will try to register new Network App at CAPIF Core.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Network App was not registered previously</li>
-<li>Network App was not onboarded previously</li>
-<li><strong><em>Preconditions: The administrator must have previously registered the User.</em></strong></li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Retrieve access_token by User from register</li>
-<li>Onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at invoker</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Onboard Invoker:</p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers</strong></li>
-<li>Reference Request Body: <a href="invoker_details_post_example.json" title="API Invoker Request">invoker onboarding body</a></li>
-<li>"onboardingInformation"-&gt;"apiInvokerPublicKey": must contain public key generated by Invoker.</li>
-<li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-2-onboard-network-app-already-onboarded">Test Case 2: Onboard Network App Already onboarded</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_invoker_management-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test will check second onboard of same Network App is not allowed.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Network App at CCF</li>
-<li>Onboard Network App at CCF</li>
-<li>Store signed Certificate at Network App</li>
-<li>Onboard Again the Network App at CCF</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Repeat Onboard Invoker:</p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers</strong></li>
-<li>Reference Request Body: <a href="invoker_details_post_example.json" title="API Invoker Request">invoker onboarding body</a></li>
-<li>"onboardingInformation"-&gt;"apiInvokerPublicKey": must contain public key generated by Invoker.</li>
-<li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>Response to Second Onboard of Network App must accomplish:<ol>
-<li><strong>403 Forbidden</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 403</li>
-<li>title with message "Forbidden"</li>
-<li>detail with message "Invoker Already registered".</li>
-<li>cause with message "Identical invoker public key".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-3-update-onboarded-network-app">Test Case 3: Update Onboarded Network App</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_invoker_management-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test will try to update information of previous onboard Network App at CAPIF Core.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously with {onboardingId}</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker at CCF</li>
-<li>Onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Update Onboarding Information at CCF with a minor change on "notificationDestination"</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Update information of previously onboarded Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</strong></li>
-<li>Reference Request Body is: [put invoker onboarding body]</li>
-<li>"notificationDestination": "<em>http://host.docker.internal:8086/netapp_new_callback</em>",</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>Response to Update Request (PUT) with minor change must contain:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>notificationDestination on response must contain the new value</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-4-update-not-onboarded-network-app">Test Case 4: Update Not Onboarded Network App</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_invoker_management-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test will try to update information of not onboarded Network App at CAPIF Core.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Network App was registered previously</li>
-<li>Network App was not onboarded previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker at CCF</li>
-<li>Onboard Invoker at CCF</li>
-<li>Update Onboarding Information at CCF of not onboarded</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Update information of not onboarded Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}</strong></li>
-<li>Reference Request Body is: [put invoker onboarding body]</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-</ol>
-</li>
-<li>Response to Update Request (PUT) must contain:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Please provide an existing Network App ID".</li>
-<li>cause with message "Not exist Network App ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-5-offboard-network-app">Test Case 5: Offboard Network App</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_invoker_management-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Registered Network App can be deleted.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker at CCF</li>
-<li>Onboard Invoker at CCF</li>
-<li>Offboard Invoker at CCF</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Offboard:</p>
-<ul>
-<li>Send <strong>DELETE</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-</ol>
-</li>
-<li>Response to Offboard Request (DELETE) must contain:<ol>
-<li><strong>204 No Content</strong></li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-6-offboard-not-previsouly-onboarded-network-app">Test Case 6: Offboard Not previsouly Onboarded Network App</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_invoker_management-6</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Non-Registered Network App cannot be deleted</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Network App was registered previously</li>
-<li>Network App was not onboarded previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker at CCF</li>
-<li>Offboard Invoker at CCF</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Offboard:</p>
-<ul>
-<li>Send <strong>DELETE</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Offboard Request (DELETE) must contain:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Please provide an existing Network App ID".</li>
-<li>cause with message "Not exist Network App ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-7-update-onboarded-network-app-certificate">Test Case 7: Update Onboarded Network App Certificate</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_invoker_management-7</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test will try to update public key and get a new signed certificate by CAPIF Core.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Network App was registered previously</li>
-<li>Network App was onboarded previously with {onboardingId} and {public_key_1}</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Invoker at CCF</li>
-<li>Onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Update Onboarding Information at CCF with new public key</li>
-<li>Update Onboarding Information at CCF with minor change</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a> with public_key_1.</p>
-</li>
-<li>
-<p>Create {public_key_2}</p>
-</li>
-<li>
-<p>Update information of previously onboarded Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</strong></li>
-<li>Reference Request Body is: [put invoker onboarding body]</li>
-<li>["onboardingInformation"]["apiInvokerPublicKey"]: {public_key_2},</li>
-<li>Store new certificate.</li>
-</ul>
-</li>
-<li>
-<p>Update information of previously onboarded Invoker Using new certificate:</p>
-<ul>
-<li>Send <strong>PUT</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}</strong></li>
-<li>Reference Request Body is: [put invoker onboarding body]</li>
-<li>"notificationDestination": "<em>http://host.docker.internal:8086/netapp_new_callback</em>",</li>
-<li>Use new <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Onboard request must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-<li>Response to Update Request (PUT) with new public key:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>apiInvokerCertificate with new certificate on response -&gt; store to use.</li>
-</ol>
-</li>
-<li>Response to Update Request (PUT) with minor change must contain:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>notificationDestination on response must contain the new value</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_invoker_management/invoker_details_post_example.json b/public/develop/testing/testplan/api_invoker_management/invoker_details_post_example.json
deleted file mode 100644
index c306a17..0000000
--- a/public/develop/testing/testplan/api_invoker_management/invoker_details_post_example.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "notificationDestination": "http://host.docker.internal:8086/netapp_callback",
-  "supportedFeatures": "fffffff",
-  "apiInvokerInformation": "ROBOT_TESTING_INVOKER",
-  "websockNotifConfig": {
-    "requestWebsocketUri": true,
-    "websocketUri": "websocketUri"
-  },
-  "onboardingInformation": {
-    "apiInvokerPublicKey": "{PUBLIC_KEY}",
-    "onboardingSecret": "onboardingSecret",
-    "apiInvokerCertificate": "apiInvokerCertificate"
-  },
-  "requestTestNotification": true
-}
diff --git a/public/develop/testing/testplan/api_invoker_management/invoker_details_put_example.json b/public/develop/testing/testplan/api_invoker_management/invoker_details_put_example.json
deleted file mode 100644
index 37a1eef..0000000
--- a/public/develop/testing/testplan/api_invoker_management/invoker_details_put_example.json
+++ /dev/null
@@ -1,393 +0,0 @@
-{
-  "notificationDestination": "http://host.docker.internal:8086/netapp_new_callback",
-  "supportedFeatures": "fffffff",
-  "apiInvokerInformation": "ROBOT_TESTING_INVOKER",
-  "websockNotifConfig": {
-    "requestWebsocketUri": true,
-    "websocketUri": "websocketUri"
-  },
-  "onboardingInformation": {
-    "apiInvokerPublicKey": "{PUBLIC_KEY}",
-    "onboardingSecret": "onboardingSecret",
-    "apiInvokerCertificate": "apiInvokerCertificate"
-  },
-  "requestTestNotification": true,
-  "apiList": [
-    {
-      "serviceAPICategory": "serviceAPICategory",
-      "ccfId": "ccfId",
-      "apiName": "apiName",
-      "shareableInfo": {
-        "capifProvDoms": ["capifProvDoms", "capifProvDoms"],
-        "isShareable": true
-      },
-      "supportedFeatures": "fffffff",
-      "description": "description",
-      "apiSuppFeats": "fffffff",
-      "apiId": "apiId",
-      "aefProfiles": [
-        {
-          "securityMethods": ["PSK"],
-          "versions": [
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            },
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            }
-          ],
-          "aefId": "aefId",
-          "interfaceDescriptions": [
-            {
-              "securityMethods": ["PSK"],
-              "port": 5248,
-              "ipv4Addr": "ipv4Addr"
-            },
-            { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" }
-          ]
-        },
-        {
-          "securityMethods": ["PSK"],
-          "versions": [
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            },
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            }
-          ],
-          "aefId": "aefId",
-          "interfaceDescriptions": [
-            {
-              "securityMethods": ["PSK"],
-              "port": 5248,
-              "ipv4Addr": "ipv4Addr"
-            },
-            { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" }
-          ]
-        }
-      ],
-      "pubApiPath": { "ccfIds": ["ccfIds", "ccfIds"] }
-    },
-    {
-      "serviceAPICategory": "serviceAPICategory",
-      "ccfId": "ccfId",
-      "apiName": "apiName2",
-      "shareableInfo": {
-        "capifProvDoms": ["capifProvDoms", "capifProvDoms"],
-        "isShareable": true
-      },
-      "supportedFeatures": "fffffff",
-      "description": "description",
-      "apiSuppFeats": "fffffff",
-      "apiId": "apiId",
-      "aefProfiles": [
-        {
-          "securityMethods": ["PSK"],
-          "versions": [
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            },
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            }
-          ],
-          "aefId": "aefId",
-          "interfaceDescriptions": [
-            {
-              "securityMethods": ["PSK"],
-              "port": 5248,
-              "ipv4Addr": "ipv4Addr"
-            },
-            { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" }
-          ]
-        },
-        {
-          "securityMethods": ["PSK"],
-          "versions": [
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            },
-            {
-              "apiVersion": "apiVersion",
-              "resources": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "resourceName": "resourceName",
-                  "custOpName": "custOpName",
-                  "uri": "uri",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "custOperations": [
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                },
-                {
-                  "operations": ["GET"],
-                  "description": "description",
-                  "custOpName": "custOpName",
-                  "commType": "REQUEST_RESPONSE"
-                }
-              ],
-              "expiry": "2000-01-23T04:56:07.000+00:00"
-            }
-          ],
-          "aefId": "aefId",
-          "interfaceDescriptions": [
-            {
-              "securityMethods": ["PSK"],
-              "port": 5248,
-              "ipv4Addr": "ipv4Addr"
-            },
-            { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" }
-          ]
-        }
-      ],
-      "pubApiPath": { "ccfIds": ["ccfIds", "ccfIds"] }
-    }
-  ]
-}
diff --git a/public/develop/testing/testplan/api_invoker_management/invoker_getauth_example.json b/public/develop/testing/testplan/api_invoker_management/invoker_getauth_example.json
deleted file mode 100644
index a66dad5..0000000
--- a/public/develop/testing/testplan/api_invoker_management/invoker_getauth_example.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "username": "ROBOT_TESTING_INVOKER",
-  "password": "password"
-}
diff --git a/public/develop/testing/testplan/api_logging_service/index.html b/public/develop/testing/testplan/api_logging_service/index.html
deleted file mode 100644
index de59d9e..0000000
--- a/public/develop/testing/testplan/api_logging_service/index.html
+++ /dev/null
@@ -1,683 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_logging_service/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Logging Service - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-logging-service" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Logging Service
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-logging-service">Test Plan for CAPIF Api Logging Service</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-creates-a-new-individual-capif-log-entry">Test Case 1: Creates a new individual CAPIF Log Entry.</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_logging-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF AEF can create log entry to Logging Service</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is pre-authorised (has valid aefId from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Log Entry:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body <a href="invocation_log.json" title="Log Request Body">log entry request body</a></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>InvocationLog</strong> data structure with:<ul>
-<li>aefId</li>
-<li>apiInvokerId</li>
-<li>logs</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invocation-logs/v1/{aefId}/logs/{logId}</strong></li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-2-creates-a-new-individual-capif-log-entry-with-invalid-aefid">Test Case 2:  Creates a new individual CAPIF Log Entry with Invalid aefId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_logging-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is not pre-authorised (has not valid aefId from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Log Entry:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{not-valid-aefId}/logs</strong></li>
-<li>body <a href="invocation_log.json" title="Log Request Body">log entry request body</a></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Exposer not exist".</li>
-<li>cause with message "Exposer id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-3-creates-a-new-individual-capif-log-entry-with-invalid-serviceapi">Test Case 3:  Creates a new individual CAPIF Log Entry with Invalid serviceAPI</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_logging-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Log Entry:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body [log entry request body with serviceAPI apiName apiId not valid]</li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker not exist".</li>
-<li>cause with message "Invoker id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-4-creates-a-new-individual-capif-log-entry-with-invalid-apiinvokerid">Test Case 4:  Creates a new individual CAPIF Log Entry with Invalid apiInvokerId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_logging-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Log Entry:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body [log entry request body with invokerId not valid]</li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>APIProviderEnrolmentDetails</strong> data structure.</li>
-<li>For each <strong>apiProvFuncs</strong>, we must check:<ol>
-<li><strong>apiProvFuncId</strong> is set</li>
-<li><strong>apiProvCert</strong> under <strong>regInfo</strong> is set properly</li>
-</ol>
-</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/api-provider-management/v1/registrations/{registrationId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Logging Service must accomplish:</p>
-<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker not exist".</li>
-<li>cause with message "Invoker id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Log Entry are not stored in CAPIF Database</p>
-</li>
-</ol>
-<h2 id="test-case-5-creates-a-new-individual-capif-log-entry-with-invalid-aefid-in-body">Test Case 5:  Creates a new individual CAPIF Log Entry with Invalid aefId in body</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_logging-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId in body</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF provider is pre-authorised (has valid apfId from CAPIF Authority)</li>
-<li>Service exist in CAPIF</li>
-<li>Invoker exist in CAPIF</li>
-</ul>
-<p><strong>Execution Steps</strong>:
-  1. Register Provider and Invoker CCF
-  2. Publish Service
-  3. Create Log Entry</p>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Onboarding">provider onboarding</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">invoker onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Log Entry:</p>
-<ol>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs</strong></li>
-<li>body [log entry request body with bad aefId] </li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ol>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Logging Service must accomplish:<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 401</li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "AEF id not matching in request and body".</li>
-<li>cause with message "Not identical AEF id".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_logging_service/invocation_log.json b/public/develop/testing/testplan/api_logging_service/invocation_log.json
deleted file mode 100644
index ceabcf0..0000000
--- a/public/develop/testing/testplan/api_logging_service/invocation_log.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
-    "aefId": "aefId",
-    "apiInvokerId": "apiInvokerId",
-    "logs": [
-      {
-        "apiId": "apiId",
-        "apiName": "apiName",
-        "apiVersion": "string",
-        "resourceName": "string",
-        "uri": "string",
-        "protocol": "HTTP_1_1",
-        "operation": "GET",
-        "result": "string",
-        "invocationTime": "2023-03-30T10:30:21.404Z",
-        "invocationLatency": 0,
-        "inputParameters": "string",
-        "outputParameters": "string",
-        "srcInterface": {
-          "ipv4Addr": "string",
-          "ipv6Addr": "string",
-          "fqdn": "string",
-          "port": 65535,
-          "apiPrefix": "string",
-          "securityMethods": [
-            "PSK",
-            "Oauth"
-          ]
-        },
-        "destInterface": {
-          "ipv4Addr": "string",
-          "ipv6Addr": "string",
-          "fqdn": "string",
-          "port": 65535,
-          "apiPrefix": "string",
-          "securityMethods": [
-            "PSK",
-            "string"
-          ]
-        },
-        "fwdInterface": "string"
-      }
-    ],
-    "supportedFeatures": "string"
-  }
-  
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_provider_management/index.html b/public/develop/testing/testplan/api_provider_management/index.html
deleted file mode 100644
index 7af889a..0000000
--- a/public/develop/testing/testplan/api_provider_management/index.html
+++ /dev/null
@@ -1,875 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_provider_management/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Provider Management - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-provider-management" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Provider Management
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-provider-management">Test Plan for CAPIF Api Provider Management</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-register-api-provider">Test Case 1: Register Api Provider</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that Api Provider can be registered con CCF</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Provider is pre-authorised (has valid certificate from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Create private and public key for provider and each function to register.</li>
-<li>Register Provider.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Register Provider at Provider Management:<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>APIProviderEnrolmentDetails</strong> data structure.</li>
-<li>For each <strong>apiProvFuncs</strong>, we must check:<ol>
-<li><strong>apiProvFuncId</strong> is set</li>
-<li><strong>apiProvCert</strong> under <strong>regInfo</strong> is set properly</li>
-</ol>
-</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/api-provider-management/v1/registrations/{registrationId}</strong></li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-2-register-api-provider-already-registered">Test Case 2: Register Api Provider Already registered</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Api Provider previously registered cannot be re-registered</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Create private and public key for provider and each function to register.</li>
-<li>Register Provider.</li>
-<li>Re-Register Provider.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-<li>
-<p>Re-Register Provider:</p>
-<ul>
-<li>Same regSec than Previous registration</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Re-Register Provider:<ol>
-<li><strong>403 Forbidden</strong> response.</li>
-<li>
-<p>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:</p>
-<ul>
-<li>status 403</li>
-<li>title with message "Forbidden"</li>
-<li>detail with message "Provider already registered".</li>
-<li>cause with message "Identical provider reg sec".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-3-update-registered-api-provider">Test Case 3: Update Registered Api Provider</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Registered Api Provider can be updated</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Create private and public key for provider and each function to register.</li>
-<li>Register Provider</li>
-<li>Update Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Create public and private key at provider for provider itself and each function (apf, aef and amf)</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Get Resource URL from Location</li>
-</ul>
-</li>
-<li>
-<p>Update Provider:</p>
-<ul>
-<li>Send <strong>PUT</strong> to Resource URL returned at registration <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a> with apiProvDomInfo set to ROBOT_TESTING_MOD</li>
-<li>Use AMF Certificate.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Register Provider:</p>
-<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>APIProviderEnrolmentDetails</strong> data structure.</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/api-provider-management/v1/registrations/{registrationId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Update Provider:</p>
-<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>body returned must accomplish <strong>APIProviderEnrolmentDetails</strong> data structure, with:<ul>
-<li>apiProvDomInfo set to ROBOT_TESTING_MOD</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-4-update-not-registered-api-provider">Test Case 4: Update Not Registered Api Provider</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Non-Registered Api Provider cannot be updated</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Api Provider was not registered previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Update Not Registered Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-<li>
-<p>Update Not Registered Provider:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Use AMF Certificate.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Update Not Registered Provider:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Not Exist Provider Enrolment Details".</li>
-<li>cause with message "Not found registrations to Send <strong>THIS</strong> api provider details".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-5-partially-update-registered-api-provider">Test Case 5: Partially Update Registered Api Provider</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Registered Api Provider can be partially updated</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Register Provider</li>
-<li>Partial update provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-<li>
-<p>Partial update provider:</p>
-<ul>
-<li>Send <strong>PATCH</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}</strong></li>
-<li>body <a href="provider_details_enrolment_details_patch_example.json" title="API Provider Enrolment Patch Request">provider request patch body</a></li>
-<li>Use AMF Certificate.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Partial update provider at Provider Management:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>body returned must accomplish <strong>APIProviderEnrolmentDetails</strong> data structure, with:<ul>
-<li>apiProvDomInfo with "ROBOT_TESTING_MOD"</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-6-partially-update-not-registered-api-provider">Test Case 6: Partially Update Not Registered Api Provider</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-6</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Non-Registered Api Provider cannot be partially updated  </p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Api Provider was not registered previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Register Provider</li>
-<li>Partial update provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-<li>
-<p>Partial update Provider:</p>
-<ul>
-<li>Send <strong>PATCH</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_API_PROVIDER_NOT_REGISTERED}</strong></li>
-<li>body <a href="provider_details_enrolment_details_patch_example.json" title="API Provider Enrolment Patch Request">provider request patch body</a></li>
-<li>Use AMF Certificate.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Partial update provider:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>
-<p>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:</p>
-<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Not Exist Provider Enrolment Details".</li>
-<li>cause with message "Not found registrations to Send <strong>THIS</strong> api provider details".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-7-delete-registered-api-provider">Test Case 7: Delete Registered Api Provider</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-7</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Registered Api Provider can be deleted</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Api Provider was registered previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Register Provider</li>
-<li>Delete Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-<li>
-<p>Delete registered provider:</p>
-<ul>
-<li>Send <strong>DELETE</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}</strong></li>
-<li>Use AMF Certificate.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Delete Provider:<ol>
-<li><strong>204 No Content</strong> response.</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-8-delete-not-registered-api-provider">Test Case 8: Delete Not Registered Api Provider</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_provider_management-8</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Non-Registered Api Provider cannot be deleted</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Api Provider was not registered previously</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Delete Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Create public and private key at provider for provider itself and each function (apf, aef and amf)</p>
-</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="../common_operations/user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Authentication Bearer with access_token</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-<li>
-<p>Delete registered provider at Provider Management:</p>
-<ul>
-<li>Send <strong>DELETE</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}</strong></li>
-<li>Use AMF Certificate.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Delete Provider:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Not Exist Provider Enrolment Details".</li>
-<li>cause with message "Not found registrations to Send <strong>THIS</strong> api provider details".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_provider_management/provider_details_enrolment_details_patch_example.json b/public/develop/testing/testplan/api_provider_management/provider_details_enrolment_details_patch_example.json
deleted file mode 100644
index 4dac4f4..0000000
--- a/public/develop/testing/testplan/api_provider_management/provider_details_enrolment_details_patch_example.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
-  "regSec": "<public provider key>",
-  "apiProvFuncs": [
-    {
-      "regInfo": {
-        "apiProvPubKey": "<public provider apf key>"
-      },
-      "apiProvFuncRole": "APF",
-      "apiProvFuncInfo": "APF_ROBOT_TESTING_PROVIDER"
-    },
-    {
-      "regInfo": {
-        "apiProvPubKey": "<public provider aef key>"
-      },
-      "apiProvFuncRole": "AEF",
-      "apiProvFuncInfo": "AEF_ROBOT_TESTING_PROVIDER"
-    },
-    {
-      "regInfo": {
-        "apiProvPubKey": "<public provider amf key>"
-      },
-      "apiProvFuncRole": "AMF",
-      "apiProvFuncInfo": "AMF_ROBOT_TESTING_PROVIDER"
-    }
-  ],
-  "apiProvDomInfo": "ROBOT_TESTING",
-  "suppFeat": "string",
-  "failReason": "string"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_provider_management/provider_details_post_example.json b/public/develop/testing/testplan/api_provider_management/provider_details_post_example.json
deleted file mode 100644
index 48e91ba..0000000
--- a/public/develop/testing/testplan/api_provider_management/provider_details_post_example.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "regSec": "string",
-  "apiProvFuncs": [
-    {
-      "apiProvFuncId": "string",
-      "regInfo": {
-        "apiProvPubKey": "string",
-        "apiProvCert": "string"
-      },
-      "apiProvFuncRole": "AEF",
-      "apiProvFuncInfo": "string"
-    }
-  ],
-  "apiProvDomInfo": "string",
-  "suppFeat": "string",
-  "failReason": "string"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_provider_management/provider_getauth_example.json b/public/develop/testing/testplan/api_provider_management/provider_getauth_example.json
deleted file mode 100644
index 8fc82ae..0000000
--- a/public/develop/testing/testplan/api_provider_management/provider_getauth_example.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "username": "ROBOT_TESTING_PROVIDER",
-  "password": "password"
-}
diff --git a/public/develop/testing/testplan/api_publish_service/index.html b/public/develop/testing/testplan/api_publish_service/index.html
deleted file mode 100644
index d4b8586..0000000
--- a/public/develop/testing/testplan/api_publish_service/index.html
+++ /dev/null
@@ -1,1233 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_publish_service/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Publish Service - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-publish-service" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Publish Service
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-publish-service">Test Plan for CAPIF Api Publish Service</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-publish-api-by-authorised-api-publisher">Test Case 1: Publish API by Authorised API Publisher</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher can Publish an API</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>
-<p>Register Provider at CCF and store certificates.</p>
-</li>
-<li>
-<p>Publish Service API</p>
-</li>
-<li>
-<p>Retrieve {apiId} from body and Location header with new resource created from response</p>
-</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-</li>
-<li>
-<p>Send <strong>POST</strong> to <strong>ccf_publish_url</strong>: <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></p>
-</li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Published Service API is stored in CAPIF Database</p>
-</li>
-</ol>
-<h2 id="test-case-2-publish-api-by-non-authorised-api-publisher">Test Case 2: Publish API by NON Authorised API Publisher</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher cannot Publish an API withot valid apfId </p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Publish Service API with invalid APF ID</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API with invalid APF ID at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Publisher not existing".</li>
-<li>cause with message "Publisher id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Service API is NOT stored in CAPIF Database</p>
-</li>
-</ol>
-<h2 id="test-case-3-retrieve-all-apis-published-by-authorised-apfid">Test Case 3: Retrieve all APIs Published by Authorised apfId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher can Retrieve all API published</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li>
-<li>At least 2 service APIs are published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Publish Service API <strong>service_1</strong></li>
-<li>Retrieve {apiId1} from body and Location header with new resource created from response</li>
-<li>Publish Service API <strong>service_2</strong></li>
-<li>Retrieve {apiId2} from body and Location header with new resource created from response</li>
-<li>Retrieve All published APIs and check if both are present.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Publish Other Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_2</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve all published APIs:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to service 1 Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to service 2 Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}</strong></li>
-</ol>
-</li>
-<li>
-<p>Published Service APIs are stored in CAPIF Database</p>
-</li>
-<li>
-<p>Response to Retrieve all published APIs:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li>Response body must return an array of <strong>ServiceAPIDescription</strong> data.</li>
-<li>Array must contain all previously published APIs.</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-4-retrieve-all-apis-published-by-non-authorised-apfid">Test Case 4: Retrieve all APIs Published by NON Authorised apfId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher cannot Retrieve API published when apfId is not authorised </p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Retrieve All published APIs</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Retrieve all published APIs:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>401 Non Authorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Provider not existing".</li>
-<li>cause with message "Provider id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Service API is NOT stored in CAPIF Database</p>
-</li>
-</ol>
-<h2 id="test-case-5-retrieve-single-apis-published-by-authorised-apfid">Test Case 5: Retrieve single APIs Published by Authorised apfId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher can Retrieve API published one by one</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li>
-<li>At least 2 service APIs are published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Publish Service API <strong>service_1</strong>.</li>
-<li>Retrieve {apiId1} from body and Location header with new resource created from response.</li>
-<li>Publish Service API <strong>service_2</strong>.</li>
-<li>Retrieve {apiId2} from body and Location header with new resource created from response.</li>
-<li>Retrieve <strong>service_1</strong> API Detail.</li>
-<li>Retrieve <strong>service_2</strong> API Detail.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Publish Other Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_2</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve <strong>service_1</strong> published APIs detail:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId1}</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve <strong>service_2</strong> published APIs detail:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId2}</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to service 1 Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to service 2 Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}</strong></li>
-</ol>
-</li>
-<li>
-<p>Published Service APIs are stored in CAPIF Database</p>
-</li>
-<li>
-<p>Response to Retrieve <strong>service_1</strong> published API using apiId1:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li>Response body must return a <strong>ServiceAPIDescription</strong> data.</li>
-<li>Array must contain same information than <strong>service_1</strong> published registration response.</li>
-</ol>
-</li>
-<li>
-<p>Response to Retrieve <strong>service_2</strong> published API using apiId2:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li>Response body must return a <strong>ServiceAPIDescription</strong> data.</li>
-<li>Array must contain same information than <strong>service_2</strong> published registration response.</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-6-retrieve-single-apis-non-published-by-authorised-apfid">Test Case 6: Retrieve single APIs non Published by Authorised apfId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-6</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher try to get detail of not published api.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li>
-<li>No published api</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Retrieve not published API Detail.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></li>
-<li>Retrieve not published APIs detail:<ul>
-<li>Send <strong>GET</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Retrieve for NOT published API must accomplish:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Service API not found".</li>
-<li>cause with message "No Service with specific credentials exists".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-7-retrieve-single-apis-published-by-non-authorised-apfid">Test Case 7: Retrieve single APIs Published by NON Authorised apfId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-7</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher cannot Retrieve detailed API published when apfId is not authorised </p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Publish Service API at CCF</li>
-<li>Retrieve {apiId} from body and Location header with new resource created from response.</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed <strong>Invoker Certificate</strong></li>
-<li>Retrieve detailed published API acting as Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve detailed published APIs:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/${apiId}</strong></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Retrieve Detailed published API acting as Invoker must accomplish:</p>
-<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "User not authorized".</li>
-<li>cause with message "Certificate not authorized".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Service API is NOT stored in CAPIF Database</p>
-</li>
-</ol>
-<h2 id="test-case-8-update-api-published-by-authorised-apfid-with-valid-serviceapiid">Test Case 8: Update API Published by Authorised apfId with valid serviceApiId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-8</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher can Update published API with a valid serviceApiId </p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li>
-<li>A service APIs is published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Publish Service API</li>
-<li>Retrieve {apiId} from body and Location header with new resource url created from response</li>
-<li>Update published Service API.</li>
-<li>Retrieve detail of Service API</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>get resource url from location Header.</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Update published API at CCF:</p>
-<ul>
-<li>Send <strong>PUT</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with overrided apiName to <strong>service_1</strong>_modified</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve detail of service API:</p>
-<ul>
-<li>Send <strong>GET</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</strong></li>
-<li>check apiName is <strong>service_1</strong>_modified</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Update Published Service API:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiName <strong>service_1</strong>_modified</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Response to Retrieve detail of Service API:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiName <strong>service_1</strong>_modified.</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-9-update-apis-published-by-authorised-apfid-with-invalid-serviceapiid">Test Case 9: Update APIs Published by Authorised apfId with invalid serviceApiId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-9</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher cannot Update published API with a invalid serviceApiId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Update published Service API.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Update published API at CCF:</p>
-<ul>
-<li>Send <strong>PUT</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with overrided apiName to <strong><em>service_1</em>*_modified</strong>*</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Update Published Service API:</p>
-<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Service API not found".</li>
-<li>cause with message "Service API id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-10-update-apis-published-by-non-authorised-apfid">Test Case 10: Update APIs Published by NON Authorised apfId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-10</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher cannot Update API published when apfId is not authorised</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Publish Service API at CCF</li>
-<li>Retrieve {apiId} from body and Location header with new resource created from response.</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed <strong>Invoker Certificate</strong></li>
-<li>Update published API at CCF as Invoker</li>
-<li>Retrieve detail of Service API as publisher</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Update published API at CCF:</p>
-<ul>
-<li>Send <strong>PUT</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with overrided apiName to <strong><em>service_1</em>*_modified</strong>*</li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve detail of service API:</p>
-<ul>
-<li>Send <strong>GET</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</strong></li>
-<li>check apiName is <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Update published API acting as Invoker must accomplish:</p>
-<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "User not authorized".</li>
-<li>cause with message "Certificate not authorized".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Response to Retrieve Detail of Service API:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiName <strong>service_1</strong>.</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-11-delete-api-published-by-authorised-apfid-with-valid-serviceapiid">Test Case 11: Delete API Published by Authorised apfId with valid serviceApiId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-11</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher can Delete published API with a valid serviceApiId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority).</li>
-<li>A service APIs is published.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Publish Service API</li>
-<li>Retrieve {apiId} from body and Location header with new resource created from response</li>
-<li>Remove published API at CCF</li>
-<li>Try to retreive deleted service API from CCF</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Remove published Service API at CCF:</p>
-<ul>
-<li>Send <strong>DELETE</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Retrieve detail of service API:<ul>
-<li>Send <strong>GET</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Response to Publish request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>ServiceAPIDescription</strong> data structure with:<ul>
-<li>apiId</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}</strong></li>
-</ol>
-</li>
-<li>
-<p>Published Service API is stored in CAPIF Database</p>
-</li>
-<li>
-<p>Response to Remove published Service API at CCF:</p>
-<ol>
-<li><strong>204 No Content</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Retrieve for DELETED published API must accomplish:</p>
-<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Service API not found".</li>
-<li>cause with message "No Service with specific credentials exists".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-12-delete-apis-published-by-authorised-apfid-with-invalid-serviceapiid">Test Case 12: Delete APIs Published by Authorised apfId with invalid serviceApiId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-12</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher cannot Delete with invalid serviceApiId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority).</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Remove published API at CCF with invalid serviceId</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Remove published Service API at CCF with invalid serviceId:</p>
-<ul>
-<li>Send <strong>DELETE</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Remove published Service API at CCF:<ol>
-<li><strong>404 Not Found</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status 404</li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Service API not found".</li>
-<li>cause with message "Service API id not found".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-13-delete-apis-published-by-non-authorised-apfid">Test Case 13: Delete APIs Published by NON Authorised apfId</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_api_publish_service-12</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Publisher cannot Delete API published when apfId is not authorised</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority).</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF and store certificates.</li>
-<li>Register Invoker and onboard Invoker at CCF</li>
-<li>Remove published API at CCF with invalid serviceId as Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body <a href="service_api_description_post_example.json" title="Service API Description Request">service api description</a> with apiName <strong>service_1</strong></li>
-<li>Get apiId</li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Remove published Service API at CCF with invalid serviceId as Invoker:</p>
-<ul>
-<li>Send <strong>DELETE</strong> to resource URL <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}</strong></li>
-<li>Use <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Remove published Service API at CCF:<ol>
-<li><strong>401 Unauthorized</strong></li>
-<li>Error Response Body must accomplish with <strong>ProblemDetails</strong> data structure with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "User not authorized".</li>
-<li>cause with message "Certificate not authorized".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_publish_service/publisher_register_body.json b/public/develop/testing/testplan/api_publish_service/publisher_register_body.json
deleted file mode 100644
index fc26db2..0000000
--- a/public/develop/testing/testplan/api_publish_service/publisher_register_body.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "password": "password",
-  "username": "ROBOT_TESTING_PUBLISHER",
-  "role": "provider",
-  "description": "Testing",
-  "cn": "ROBOT_TESTING_PUBLISHER"
-}
diff --git a/public/develop/testing/testplan/api_publish_service/service_api_description_post_example.json b/public/develop/testing/testplan/api_publish_service/service_api_description_post_example.json
deleted file mode 100644
index b725b42..0000000
--- a/public/develop/testing/testplan/api_publish_service/service_api_description_post_example.json
+++ /dev/null
@@ -1,113 +0,0 @@
-{
-  "apiName": "service_1",
-  "aefProfiles": [
-    {
-      "aefId": "string",
-      "versions": [
-        {
-          "apiVersion": "v1",
-          "expiry": "2021-11-30T10:32:02.004Z",
-          "resources": [
-            {
-              "resourceName": "string",
-              "commType": "REQUEST_RESPONSE",
-              "uri": "string",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ],
-          "custOperations": [
-            {
-              "commType": "REQUEST_RESPONSE",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ]
-        }
-      ],
-      "protocol": "HTTP_1_1",
-      "dataFormat": "JSON",
-      "securityMethods": ["PSK"],
-      "interfaceDescriptions": [
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        },
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        }
-      ]
-    },
-    {
-      "aefId": "string",
-      "versions": [
-        {
-          "apiVersion": "v1",
-          "expiry": "2021-11-30T10:32:02.004Z",
-          "resources": [
-            {
-              "resourceName": "string",
-              "commType": "REQUEST_RESPONSE",
-              "uri": "string",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ],
-          "custOperations": [
-            {
-              "commType": "REQUEST_RESPONSE",
-              "custOpName": "string",
-              "operations": [
-                "GET"
-              ],
-              "description": "string"
-            }
-          ]
-        }
-      ],
-      "protocol": "HTTP_1_1",
-      "dataFormat": "JSON",
-      "securityMethods": ["PSK"],
-      "interfaceDescriptions": [
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        },
-        {
-          "ipv4Addr": "string",
-          "port": 65535,
-          "securityMethods": ["PSK"]
-        }
-      ]
-    }
-  ],
-  "description": "string",
-  "supportedFeatures": "fffff",
-  "shareableInfo": {
-    "isShareable": true,
-    "capifProvDoms": [
-      "string"
-    ]
-  },
-  "serviceAPICategory": "string",
-  "apiSuppFeats": "fffff",
-  "pubApiPath": {
-    "ccfIds": [
-      "string"
-    ]
-  },
-  "ccfId": "string"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_security_service/access_token_req.json b/public/develop/testing/testplan/api_security_service/access_token_req.json
deleted file mode 100644
index 8504736..0000000
--- a/public/develop/testing/testplan/api_security_service/access_token_req.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-    "client_id": "client_id",
-    "client_secret": "client_secret",
-    "grant_type": "client_credentials",
-    "scope": "scope"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_security_service/access_token_req_example.json b/public/develop/testing/testplan/api_security_service/access_token_req_example.json
deleted file mode 100644
index 070a717..0000000
--- a/public/develop/testing/testplan/api_security_service/access_token_req_example.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "client_id": "bb260b4d0b3a0f954fa23f42d979ca",
-  "grant_type": "client_credentials",
-  "scope": "3gpp#af7e4cf70063814770e7b00b87273e:service_1"
-}
diff --git a/public/develop/testing/testplan/api_security_service/index.html b/public/develop/testing/testplan/api_security_service/index.html
deleted file mode 100644
index ace5eb9..0000000
--- a/public/develop/testing/testplan/api_security_service/index.html
+++ /dev/null
@@ -1,1946 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/api_security_service/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan for CAPIF Api Security Service - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-for-capif-api-security-service" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan for CAPIF Api Security Service
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-for-capif-api-security-service">Test Plan for CAPIF Api Security Service</h1>
-<p>At this documentation you will have all information and related files and examples of test plan for this API.</p>
-<h2 id="test-case-1-create-a-security-context-for-an-api-invoker">Test Case 1: Create a security context for an API invoker</h2>
-<p><strong>Test ID</strong>: <strong><em>capif_security_api-1</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Invoker can create a Security context</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Create Security Context for this Invoker<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Create security context:<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}</strong></li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-2-create-a-security-context-for-an-api-invoker-with-provider-role">Test Case 2: Create a security context for an API invoker with Provider role</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-2</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Provider cannot create a Security context with valid apiInvokerId.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context using Provider certificate</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker but using Provider certificate.</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Create security context using Provider certificate:</p>
-<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be invoker".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>No context stored at DB</p>
-</li>
-</ol>
-<h2 id="test-case-3-create-a-security-context-for-an-api-invoker-with-provider-entity-role-and-invalid-apiinvokerid">Test Case 3: Create a security context for an API invoker with Provider entity role and invalid apiInvokerId</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-3</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Provider cannot create a Security context with invalid apiInvokerID.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Create Security Context using Provider certificate</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Create Security Context for this not valid apiInvokerId and using Provider certificate.</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Create security context using Provider certificate:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be invoker".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>No context stored at DB</li>
-</ol>
-<h2 id="test-case-4-create-a-security-context-for-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid">Test Case 4: Create a security context for an API invoker with Invoker entity role and invalid apiInvokerId</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-4</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Invoker cannot create a Security context with valid apiInvokerId.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with invalid apiInvokerId</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Create Security Context using Provider certificate</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Create security context using Provider certificate:</p>
-<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker not found".</li>
-<li>cause with message "API Invoker not exists or invalid ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>No context stored at DB</p>
-</li>
-</ol>
-<h2 id="test-case-5-retrieve-the-security-context-of-an-api-invoker">Test Case 5: Retrieve the Security Context of an API Invoker</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-5</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an provider can retrieve the Security context of an API Invoker</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context using Provider certificate</li>
-<li>Retrieve Security Context by Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker.</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Retrieve security context:<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-6-retrieve-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid">Test Case 6: Retrieve the Security Context of an API Invoker with invalid apiInvokerID</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-6</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an provider can retrieve the Security context of an API Invoker</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Create Security Context using Provider certificate</li>
-<li>Retrieve Security Context by Provider of invalid invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Retrieve Security Context of invalid Invoker by Provider:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</strong></li>
-<li>Using <strong>AEF Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Retrieve security context:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker not found".</li>
-<li>cause with message "API Invoker not exists or invalid ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-7-retrieve-the-security-context-of-an-api-invoker-with-invalid-apfid">Test Case 7: Retrieve the Security Context of an API Invoker with invalid apfId</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-7</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Provider cannot retrieve the Security context of an API Invoker without valid apfId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Exposure Function is not pre-authorised (has invalid apfId)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Store signed Certificate</li>
-<li>Create Security Context</li>
-<li>Retrieve Security Context as Provider.</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve Security Context as Invoker role:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Create security context:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be aef".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-8-delete-the-security-context-of-an-api-invoker">Test Case 8: Delete the Security Context of an API Invoker</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-8</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Provider can delete a Security context</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context using Provider certificate</li>
-<li>Delete Security Context by Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker but using Provider certificate.</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Delete Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>DELETE</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Delete security context:</p>
-<ol>
-<li><strong>204 No Content</strong> response.</li>
-</ol>
-</li>
-<li>
-<p>Retrieve security context:</p>
-<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Security context not found".</li>
-<li>cause with message "API Invoker not exists or invalid ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-9-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role">Test Case 9: Delete the Security Context of an API Invoker with Invoker entity role</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-9</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Invoker cannot delete a Security context</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Create Security Context using Provider certificate</li>
-<li>Delete Security Context by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Delete Security Context of Invoker:</p>
-<ul>
-<li>Send <strong>DELETE</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Delete security context:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be aef".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-10-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid">Test Case 10: Delete the Security Context of an API Invoker with Invoker entity role and invalid apiInvokerID</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-10</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Invoker cannot delete a Security context with invalid </p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Invoker is pre-authorised.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Delete Security Context by invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Delete Security Context of Invoker:</p>
-<ul>
-<li>Send <strong>DELETE</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</strong></li>
-<li>Use <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Delete security context:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be aef".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-11-delete-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid">Test Case 11: Delete the Security Context of an API Invoker with invalid apiInvokerID</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-11</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Provider cannot delete a Security context of invalid apiInvokerId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>Provider is pre-authorised (has valid apfId from CAPIF Authority).</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Delete Security Context by provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Delete Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>DELETE</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}</strong></li>
-<li>Use <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Retrieve security context:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker not found".</li>
-<li>cause with message "API Invoker not exists or invalid ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-12-update-the-security-context-of-an-api-invoker">Test Case 12: Update the Security Context of an API Invoker</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-12</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Invoker can update a Security context</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context By Invoker</li>
-<li>Update Security Context By Invoker</li>
-<li>Retrieve Security Context By Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-<li>
-<p>Update Security Context of Invoker:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a> but with notification destination modified to <strong>http://robot.testing2</strong></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-<li>
-<p>Retrieve Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Using <strong>AEF Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Update security context:</p>
-<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.</li>
-</ol>
-</li>
-<li>
-<p>Retrieve security context:</p>
-<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.<ol>
-<li>Check is this returned object match with modified one.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-13-update-the-security-context-of-an-api-invoker-with-provider-entity-role">Test Case 13: Update the Security Context of an API Invoker with Provider entity role</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-13</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Provider cannot update a Security context</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized.</li>
-<li>Invoker has created the Security Context previously.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context</li>
-<li>Update Security Context as Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-<li>
-<p>Update Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a> but with notification destination modified to <strong>http://robot.testing2</strong></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Update security context:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be invoker". </li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-14-update-the-security-context-of-an-api-invoker-with-aef-entity-role-and-invalid-apiinvokerid">Test Case 14: Update the Security Context of an API Invoker with AEF entity role and invalid apiInvokerId</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-14</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Provider cannot update a Security context of invalid apiInvokerId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized.</li>
-<li>Invoker has created the Security Context previously.</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF</li>
-<li>Update Security Context as Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a></p>
-</li>
-<li>
-<p>Update Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Update security context:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be invoker". </li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-15-update-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid">Test Case 15: Update the Security Context of an API Invoker with invalid apiInvokerID</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-15</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Invoker cannot update a Security context not valid apiInvokerId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Update Security Context</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Update Security Context of Invoker:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Retrieve security context:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker not found".</li>
-<li>cause with message "API Invoker not exists or invalid ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-16-revoke-the-authorization-of-the-api-invoker-for-apis">Test Case 16: Revoke the authorization of the API invoker for APIs.</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-16</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that a Provider can revoke the authorization for APIs</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context by Invoker</li>
-<li>Revoke Security Context by Provider</li>
-<li>Retrieve Security Context by Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context By Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Revoke Authorization by Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete</strong></li>
-<li>body <a href="security_notification.json" title="Security Notification Request">security notification body</a></li>
-<li>Using <strong>AEF Certificate</strong>.</li>
-</ul>
-</li>
-<li>
-<p>Retrieve Security Context by Provider:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Using <strong>AEF Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Revoke Authorization:</p>
-<ol>
-<li><strong>204 No Content</strong> response.</li>
-</ol>
-</li>
-<li>
-<p>Retrieve security context:</p>
-<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Security context not found".</li>
-<li>cause with message "API Invoker has no security context".</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-17-revoke-the-authorization-of-the-api-invoker-for-apis-without-valid-apfid">Test Case 17: Revoke the authorization of the API invoker for APIs without valid apfID.</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-17</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an Invoker can't revoke the authorization for APIs</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context</li>
-<li>Revoke Security Context by invoker</li>
-<li>Retrieve Security Context</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-<li>
-<p>Revoke Authorization by invoker:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete</strong></li>
-<li>body <a href="security_notification.json" title="Security Notification Request">security notification body</a></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Retrieve Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>Using Provider Certificate</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Revoke Security Context by invoker:</p>
-<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>401</strong></li>
-<li>title with message "Unauthorized"</li>
-<li>detail with message "Role not authorized for this API route".</li>
-<li>cause with message "User role must be provider". </li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Retrieve security context:</p>
-<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.<ol>
-<li>Check is this returned object match with created one.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-18-revoke-the-authorization-of-the-api-invoker-for-apis-with-invalid-apiinvokerid">Test Case 18: Revoke the authorization of the API invoker for APIs with invalid apiInvokerId.</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-18</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register and onboard Invoker at CCF</li>
-<li>Register Provider at CCF</li>
-<li>Create Security Context</li>
-<li>Revoke Security Context by Provider</li>
-<li>Retrieve Security Context</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Create Security Context for this Invoker:</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-<li>
-<p>Revoke Authorization by Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/delete</strong></li>
-<li>body <a href="security_notification.json" title="Security Notification Request">security notification body</a></li>
-<li>Using <strong>AEF Certificate</strong>.</li>
-</ul>
-</li>
-<li>
-<p>Retrieve Security Context of Invoker by Provider:</p>
-<ul>
-<li>Send <strong>GET</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}?authenticationInfo=true&amp;authorizationInfo=true</strong></li>
-<li>This request will ask with parameter to retrieve authenticationInfo and authorizationInfo</li>
-<li>Using <strong>AEF Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>
-<p>Revoke Security Context by invoker:</p>
-<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails</strong> data structure, with:<ul>
-<li>status <strong>404</strong></li>
-<li>title with message "Not Found"</li>
-<li>detail with message "Invoker not found".</li>
-<li>cause with message "API Invoker not exists or invalid ID".</li>
-</ul>
-</li>
-</ol>
-</li>
-<li>
-<p>Retrieve security context:</p>
-<ol>
-<li><strong>200 OK</strong> response.</li>
-<li>body returned must accomplish <strong>ServiceSecurity</strong> data structure.<ol>
-<li>Check is this return one object that match with created one.</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-19-retrieve-access-token">Test Case 19: Retrieve access token</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-19</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Invoker can retrieve a security access token OAuth 2.0.</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerId)</li>
-<li>Service API of Provider is published</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by invoker:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{securityId}/token</strong>:</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a> and example <a href="access_token_req.json" title="Access Token Request Example">example</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId.</li>
-<li><strong><em>grant_type=client_credentials</em></strong>.</li>
-<li>Create Scope properly for request: <strong><em>3gpp#{aef_id}:{api_name}</em></strong></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>200 OK</strong></li>
-<li>body must follow <strong>AccessTokenRsp</strong> with:<ol>
-<li>access_token present</li>
-<li>token_type=Bearer</li>
-</ol>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-20-retrieve-access-token-by-provider">Test Case 20: Retrieve access token by Provider</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-20</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by provider:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{securityId}/token</strong>:</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=client_credentials</em></strong></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>AccessTokenErr</strong> data structure, with:<ul>
-<li>error unauthorized_client</li>
-<li>error_description=Role not authorized for this API route</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-21-retrieve-access-token-by-provider-with-invalid-apiinvokerid">Test Case 21: Retrieve access token by Provider with invalid apiInvokerId</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-21</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot retrieve a security access token without valid apiInvokerId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Provider</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by provider:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token</strong>.</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=client_credentials</em></strong></li>
-<li>Using <strong>AEF Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>401 Unauthorized</strong> response.</li>
-<li>body returned must accomplish <strong>AccessTokenErr</strong> data structure, with:<ul>
-<li>error unauthorized_client</li>
-<li>error_description=Role not authorized for this API route</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-22-retrieve-access-token-with-invalid-apiinvokerid">Test Case 22: Retrieve access token with invalid apiInvokerId</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-22</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Invoker can't retrieve a security access token without valid apiInvokerId</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised (has valid apiInvokerId)</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></li>
-<li>Publish Service API at CCF:<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>Request Discover Published APIs not filtered:<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>Create Security Context for this Invoker<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>Request Access Token by invoker:<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token</strong>.</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=client_credentials</em></strong></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>404 Not Found</strong> response.</li>
-<li>body returned must accomplish <strong>ProblemDetails29571</strong> data structure, with:<ul>
-<li>status 404</li>
-<li>title Not Found</li>
-<li>detail Security context not found</li>
-<li>cause API Invoker has no security context</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<p><strong>NOTE: ProblemDetails29571 is the definition present for this request at swagger of ProblemDetails, and this is different from definition of ProblemDetails across other CAPIF Services</strong></p>
-<h2 id="test-case-23-retrieve-access-token-with-invalid-client_id">Test Case 23: Retrieve access token with invalid client_id</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-23</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot retrieve a security access token without valid client_id at body</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by invoker:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{securityId}/token</strong>.</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=client_credentials</em></strong></li>
-<li><strong>client_id is not-valid</strong> </li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>400 Bad Request</strong> response.</li>
-<li>body returned must accomplish <strong>AccessTokenErr</strong> data structure, with:<ul>
-<li>error invalid_client</li>
-<li>error_description=Client Id not found</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-24-retrieve-access-token-with-unsupported-grant_type">Test Case 24: Retrieve access token with unsupported grant_type</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-24</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot retrieve a security access token with unsupported grant_type</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by invoker:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{securityId}/token</strong>.</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=not_valid</em></strong></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>400 Bad Request</strong> response.</li>
-<li>body returned must accomplish <strong>AccessTokenErr</strong> data structure, with:<ul>
-<li>error unsupported_grant_type</li>
-<li>error_description=Invalid value for <code>grant_type</code> \(${grant_type}\), must be one of \['client_credentials'\] - 'grant_type'</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-25-retrieve-access-token-with-invalid-scope">Test Case 25: Retrieve access token with invalid scope</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-25</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot retrieve a security access token with complete invalid scope</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by invoker:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{securityId}/token</strong>.</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=client_credentials</em></strong></li>
-<li><strong><em>scope=not-valid-scope</em></strong></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>400 Bad Request</strong> response.</li>
-<li>body returned must accomplish <strong>AccessTokenErr</strong> data structure, with:<ul>
-<li>error invalid_scope</li>
-<li>error_description=The first characters must be '3gpp'</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-26-retrieve-access-token-with-invalid-aefid-at-scope">Test Case 26: Retrieve access token with invalid aefid at scope</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-26</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot retrieve a security access token with invalid aefId at scope</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by invoker:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{securityId}/token</strong>.</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=client_credentials</em></strong></li>
-<li><strong><em>scope=3gpp#1234:</em>*service_1</strong>*</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>400 Bad Request</strong> response.</li>
-<li>body returned must accomplish <strong>AccessTokenErr</strong> data structure, with:<ul>
-<li>error invalid_scope</li>
-<li>error_description=One of aef_id not belongs of your security context</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-<h2 id="test-case-27-retrieve-access-token-with-invalid-apiname-at-scope">Test Case 27: Retrieve access token with invalid apiName at scope</h2>
-<p><strong>Test ID</strong>:: <strong><em>capif_security_api-27</em></strong></p>
-<p><strong>Description</strong>:</p>
-<p>This test case will check that an API Exposure Function cannot retrieve a security access token with invalid apiName at scope</p>
-<p><strong>Pre-Conditions</strong>:</p>
-<ul>
-<li>API Invoker is pre-authorised and Provider is also authorized</li>
-</ul>
-<p><strong>Execution Steps</strong>:</p>
-<ol>
-<li>Register Provider at CCF, store certificates and Publish Service API <strong>service_1</strong> at CCF</li>
-<li>Register and onboard Invoker at CCF</li>
-<li>Discover Service APIs by Invoker.</li>
-<li>Create Security Context According to Service APIs discovered.</li>
-<li>Request Access Token by Invoker</li>
-</ol>
-<p><strong>Information of Test</strong>:</p>
-<ol>
-<li>
-<p>Perform <a href="../common_operations/#register-a-provider" title="Provider Registration">Provider Registration</a> and <a href="../common_operations/#onboard-an-invoker" title="Invoker Onboarding">Invoker Onboarding</a></p>
-</li>
-<li>
-<p>Publish Service API at CCF:</p>
-<ul>
-<li>Send <strong>POST</strong> to ccf_publish_url <strong>https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis</strong></li>
-<li>body [service api description] with apiName <strong>service_1</strong></li>
-<li>Use <strong>APF Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Request Discover Published APIs not filtered:</p>
-<ul>
-<li>Send <strong>GET</strong> to ccf_discover_url <strong>https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}</strong></li>
-<li>Param api-invoker-id is mandatory</li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-<li>
-<p>Create Security Context for this Invoker</p>
-<ul>
-<li>Send <strong>PUT</strong> <strong>https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}</strong></li>
-<li>body <a href="service_security.json" title="Service Security Request">service security body</a></li>
-<li>Using <strong>Invoker Certificate</strong>.</li>
-<li>Create Security Information Body with one <strong>securityInfo</strong> for each aef present at each serviceAPIDescription present at Discover.</li>
-</ul>
-</li>
-<li>
-<p>Request Access Token by invoker:</p>
-<ul>
-<li>Sent POST <strong>https://{CAPIF_HOSTNAME}/securities/{securityId}/token</strong>.</li>
-<li>body <a href="access_token_req.json" title="Access Token Request">access token req body</a></li>
-<li><strong><em>securityId</em></strong> is apiInvokerId</li>
-<li><strong><em>grant_type=client_credentials</em></strong></li>
-<li><strong><em>scope=3gpp#{aef_id}:not-valid</em></strong></li>
-<li>Using <strong>Invoker Certificate</strong></li>
-</ul>
-</li>
-</ol>
-<p><strong>Expected Result</strong>:</p>
-<ol>
-<li>Response to Request of Access Token:<ol>
-<li><strong>400 Bad Request</strong> response.</li>
-<li>body returned must accomplish <strong>AccessTokenErr</strong> data structure, with:<ul>
-<li>error invalid_scope</li>
-<li>error_description=One of the api names does not exist or is not associated with the aef id provided</li>
-</ul>
-</li>
-</ol>
-</li>
-</ol>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_security_service/security_notification.json b/public/develop/testing/testplan/api_security_service/security_notification.json
deleted file mode 100644
index 6b94eb5..0000000
--- a/public/develop/testing/testplan/api_security_service/security_notification.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "aefId": "aefId",
-    "apiIds": [
-        "apiIds",
-        "apiIds"
-    ],
-    "apiInvokerId": "api_invoker_id",
-    "cause": "OVERLIMIT_USAGE"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/api_security_service/service_security.json b/public/develop/testing/testplan/api_security_service/service_security.json
deleted file mode 100644
index ad7bc1a..0000000
--- a/public/develop/testing/testplan/api_security_service/service_security.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "notificationDestination": "http://robot.testing",
-    "supportedFeatures": "fffffff",
-    "securityInfo": [{
-        "authenticationInfo": "authenticationInfo",
-        "authorizationInfo": "authorizationInfo",
-        "interfaceDetails": {
-            "ipv4Addr": "127.0.0.1",
-            "securityMethods": ["PSK"],
-            "port": 5248
-        },
-        "prefSecurityMethods": ["PSK", "PKI", "OAUTH"],
-    },
-    {
-        "authenticationInfo": "authenticationInfo",
-        "authorizationInfo": "authorizationInfo",
-        "prefSecurityMethods": ["PSK", "PKI", "OAUTH"],
-        "aefId": "aefId"
-    }],
-    "websockNotifConfig": {
-        "requestWebsocketUri": true,
-        "websocketUri": "websocketUri"
-    },
-    "requestTestNotification": true
-}
diff --git a/public/develop/testing/testplan/common_operations/index.html b/public/develop/testing/testplan/common_operations/index.html
deleted file mode 100644
index d342a55..0000000
--- a/public/develop/testing/testplan/common_operations/index.html
+++ /dev/null
@@ -1,551 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/common_operations/">
-      
-      
-      
-      
-      <link rel="icon" href="../../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Common Operations - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#common-operations" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Common Operations
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="common-operations">Common Operations</h1>
-<h2 id="register-new-user">Register new user</h2>
-<p>In order to use OpenCAPIF we must add a new user. This new user can onboard/register any Invokers or Providers.</p>
-<p>That new user <strong>must be created by administrator</strong> of Register Service and with the credentials shared by administrator, the new user can get the <strong>access_token</strong> by requesting it to Register service.</p>
-<p>The steps to register a new user at Register Service are:</p>
-<h3 id="admin-create-user">Admin create User</h3>
-<p>1) <strong>Login as Admin to get access_token:</strong></p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/login</strong><ul>
-<li><strong>Include basic Auth Header with Admin credentials</strong></li>
-</ul>
-</li>
-<li>Get <strong>access_token</strong> and <strong>refresh_token</strong> from response</li>
-</ul>
-<p><img alt="Flow" src="../../../images/flows/01_Login_Admin.png" /></p>
-<p>2) <strong>Create User:</strong></p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/createUser</strong><ul>
-<li>Include Admin <strong>access_token</strong> in <strong>Authorization Bearer Header</strong></li>
-<li>Body <a href="user_registration_body.json" title="User Registration Body">user_registration_body</a></li>
-</ul>
-</li>
-</ul>
-<p><img alt="Flow" src="../../../images/flows/02_Creation_of_user.png" /></p>
-<h3 id="user-retrieve-access-token-and-other-information">User Retrieve access token and other information</h3>
-<p>1) <strong>Retrieve access_token by User:</strong></p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong><ul>
-<li>Include <strong>basic Auth Header with User credentials</strong></li>
-</ul>
-</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-<p><img alt="Flow" src="../../../images/flows/03_Register_of_AEF_GetAuth.png" /></p>
-<h2 id="onboard-an-invoker">Onboard an Invoker</h2>
-<h3 id="steps-to-perform-operation">Steps to perform operation</h3>
-<p><strong><em>Preconditions: The administrator must have previously registered the User.</em></strong></p>
-<ol>
-<li>Create public and private key at invoker</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Onboard Invoker:     </p>
-<ul>
-<li>Send <strong>POST</strong> to <strong>https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers</strong></li>
-<li>Reference Request Body: <a href="../api_invoker_management/invoker_details_post_example.json" title="API Invoker Request">invoker onboarding body</a></li>
-<li>"onboardingInformation"-&gt;"apiInvokerPublicKey": must contain public key generated by Invoker.</li>
-<li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li>
-</ul>
-</li>
-</ol>
-<h3 id="checks-to-ensure-onboarding">Checks to ensure onboarding</h3>
-<ol>
-<li>
-<p>Response to Get Auth:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li><strong><em>access_token</em></strong> returned.</li>
-</ol>
-</li>
-<li>
-<p>Response to Onboard request must accomplish:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-<li>Response Body must follow <strong>APIInvokerEnrolmentDetails</strong> data structure with:<ul>
-<li>apiInvokerId</li>
-<li>onboardingInformation-&gt;apiInvokerCertificate must contain the public key signed.</li>
-</ul>
-</li>
-<li>Response Header <strong>Location</strong> must be received with URI to new resource created, following this structure: <strong>{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}</strong></li>
-</ol>
-</li>
-</ol>
-<h3 id="example-flow">Example Flow</h3>
-<p><img alt="Flow" src="../../../images/flows/07_Invoker_Onboarding.png" /></p>
-<h2 id="register-a-provider">Register a Provider</h2>
-<h3 id="steps-to-perform-operation_1">Steps to Perform operation</h3>
-<ol>
-<li>Create public and private key at provider for provider itself and each function (apf, aef and amf)</li>
-<li>
-<p>Retrieve access_token by User:</p>
-<ul>
-<li>Send <strong>GET</strong> to <strong>https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/getauth</strong></li>
-<li>Include basic Auth Header with Admin user/password</li>
-<li>Retrieve <strong>access_token</strong> and the urls needed for next requests from response body <a href="user_getauth_response_body_example.json" title="User GetAuth response Body Example">user_getauth_response_body_example</a></li>
-</ul>
-</li>
-<li>
-<p>Register Provider:</p>
-<ul>
-<li>Send <strong>POST</strong> <strong>https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations</strong></li>
-<li>body <a href="../api_provider_management/provider_details_post_example.json" title="API Provider Enrolment Request">provider request body</a></li>
-<li>Send in Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token})</li>
-<li>Store each cert in a file with according name.</li>
-</ul>
-</li>
-</ol>
-<h3 id="checks-to-ensure-provider-registration">Checks to ensure provider registration</h3>
-<ol>
-<li>
-<p>Response to Register:</p>
-<ol>
-<li><strong>201 Created</strong></li>
-</ol>
-</li>
-<li>
-<p>Response to Get Auth:</p>
-<ol>
-<li><strong>200 OK</strong></li>
-<li><strong><em>access_token</em></strong> returned.</li>
-</ol>
-</li>
-<li>
-<p>Register Provider at Provider Management:</p>
-<ol>
-<li><strong>201 Created</strong> response.</li>
-<li>body returned must accomplish <strong>APIProviderEnrolmentDetails</strong> data structure.</li>
-<li>For each <strong>apiProvFuncs</strong>, we must check:<ol>
-<li><strong>apiProvFuncId</strong> is set</li>
-<li><strong>apiProvCert</strong> under <strong>regInfo</strong> is set properly</li>
-</ol>
-</li>
-<li>Location Header must contain the new resource URL <strong>{apiRoot}/api-provider-management/v1/registrations/{registrationId}</strong></li>
-</ol>
-</li>
-</ol>
-<h3 id="example-flow_1">Example Flow</h3>
-<p><img alt="Flow" src="../../../images/flows/07_Invoker_Onboarding.png" /></p>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/develop/testing/testplan/common_operations/user_getauth_response_body_example.json b/public/develop/testing/testplan/common_operations/user_getauth_response_body_example.json
deleted file mode 100644
index a4a71fe..0000000
--- a/public/develop/testing/testplan/common_operations/user_getauth_response_body_example.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "access_token": "eyJhbGciOiJS...",
-    "ca_root": "-----BEGIN CERTIFICATE----- ...",
-    "ccf_api_onboarding_url": "api-provider-management/v1/registrations",
-    "ccf_discover_url": "service-apis/v1/allServiceAPIs?api-invoker-id=",
-    "ccf_onboarding_url": "api-invoker-management/v1/onboardedInvokers",
-    "ccf_publish_url": "published-apis/v1/<apfId>/service-apis",
-    "ccf_security_url": "capif-security/v1/trustedInvokers/<apiInvokerId>",
-    "message": "Token and CA root returned successfully"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/common_operations/user_registration_body.json b/public/develop/testing/testplan/common_operations/user_registration_body.json
deleted file mode 100644
index 123c1e1..0000000
--- a/public/develop/testing/testplan/common_operations/user_registration_body.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-    "username": "customUser",
-    "password": "password",
-    "description": "description",
-    "email": "customuser@telefonica.com"
-}
\ No newline at end of file
diff --git a/public/develop/testing/testplan/index.html b/public/develop/testing/testplan/index.html
deleted file mode 100644
index 7ce75a0..0000000
--- a/public/develop/testing/testplan/index.html
+++ /dev/null
@@ -1,431 +0,0 @@
-
-<!doctype html>
-<html lang="en" class="no-js">
-  <head>
-    
-      <meta charset="utf-8">
-      <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-        <meta name="description" content="ETSI SDG TFS Documentation page">
-      
-      
-        <meta name="author" content="TeraflowSDN by ETSI">
-      
-      
-        <link rel="canonical" href="https://tfs.etsi.org/develop/testing/testplan/">
-      
-      
-      
-      
-      <link rel="icon" href="../../images/favicon.png">
-      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.42">
-    
-    
-      
-        <title>Test Plan Index - ETSI SDG TFS Documentation</title>
-      
-    
-    
-      <link rel="stylesheet" href="../../assets/stylesheets/main.0253249f.min.css">
-      
-        
-        <link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
-        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
-        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
-      <link rel="stylesheet" href="../../stylesheets/extra.css">
-    
-    <script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
-
-    
-    
-    
-  </head>
-  
-  
-    
-    
-    
-    
-    
-    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="0D47A1" data-md-color-accent="1565C0">
-  
-    
-    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
-    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
-    <label class="md-overlay" for="__drawer"></label>
-    <div data-md-component="skip">
-      
-        
-        <a href="#test-plan-index" class="md-skip">
-          Skip to content
-        </a>
-      
-    </div>
-    <div data-md-component="announce">
-      
-    </div>
-    
-      <div data-md-color-scheme="default" data-md-component="outdated" hidden>
-        
-      </div>
-    
-    
-      
-
-  
-
-<header class="md-header md-header--shadow" data-md-component="header">
-  <nav class="md-header__inner md-grid" aria-label="Header">
-    <a href="../.." title="ETSI SDG TFS Documentation" class="md-header__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    <label class="md-header__button md-icon" for="__drawer">
-      
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
-    </label>
-    <div class="md-header__title" data-md-component="header-title">
-      <div class="md-header__ellipsis">
-        <div class="md-header__topic">
-          <span class="md-ellipsis">
-            ETSI SDG TFS Documentation
-          </span>
-        </div>
-        <div class="md-header__topic" data-md-component="header-topic">
-          <span class="md-ellipsis">
-            
-              Test Plan Index
-            
-          </span>
-        </div>
-      </div>
-    </div>
-    
-      
-    
-    
-    
-    
-      <label class="md-header__button md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-      </label>
-      <div class="md-search" data-md-component="search" role="dialog">
-  <label class="md-search__overlay" for="__search"></label>
-  <div class="md-search__inner" role="search">
-    <form class="md-search__form" name="search">
-      <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
-      <label class="md-search__icon md-icon" for="__search">
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
-        
-        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
-      </label>
-      <nav class="md-search__options" aria-label="Search">
-        
-        <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
-          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
-        </button>
-      </nav>
-      
-    </form>
-    <div class="md-search__output">
-      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
-        <div class="md-search-result" data-md-component="search-result">
-          <div class="md-search-result__meta">
-            Initializing search
-          </div>
-          <ol class="md-search-result__list" role="presentation"></ol>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    
-      <div class="md-header__source">
-        <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-      </div>
-    
-  </nav>
-  
-</header>
-    
-    <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
-      <main class="md-main" data-md-component="main">
-        <div class="md-main__inner md-grid">
-          
-            
-              
-              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
-                <div class="md-sidebar__scrollwrap">
-                  <div class="md-sidebar__inner">
-                    
-
-
-
-  
-
-<nav class="md-nav md-nav--primary md-nav--integrated" aria-label="Navigation" data-md-level="0">
-  <label class="md-nav__title" for="__drawer">
-    <a href="../.." title="ETSI SDG TFS Documentation" class="md-nav__button md-logo" aria-label="ETSI SDG TFS Documentation" data-md-component="logo">
-      
-  <img src="../../images/logos/TeraFlow SDN Logo Screen_B_W NEG.png" alt="logo">
-
-    </a>
-    ETSI SDG TFS Documentation
-  </label>
-  
-    <div class="md-nav__source">
-      <a href="https://labs.etsi.org/rep/tfs" title="Go to repository" class="md-source" data-md-component="source">
-  <div class="md-source__icon md-icon">
-    
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-  </div>
-  <div class="md-source__repository">
-    TFS GitLab
-  </div>
-</a>
-    </div>
-  
-  <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../.." class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    Index
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../deployment_guide/deployment_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    1. Deployment Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
-    <li class="md-nav__item">
-      <a href="../../development_guide/development_guide/" class="md-nav__link">
-        
-  
-  <span class="md-ellipsis">
-    2. Development Guide
-  </span>
-  
-
-      </a>
-    </li>
-  
-
-    
-  </ul>
-</nav>
-                  </div>
-                </div>
-              </div>
-            
-            
-          
-          
-            <div class="md-content" data-md-component="content">
-              <article class="md-content__inner md-typeset">
-                
-                  
-
-
-<h1 id="test-plan-index">Test Plan Index</h1>
-<p>List of Common API Services implemented:</p>
-<ul>
-<li><a href="common_operations/">Common Operations</a></li>
-<li><a href="api_invoker_management/">Api Invoker Management</a></li>
-<li><a href="api_provider_management/">Api Provider Management</a></li>
-<li><a href="api_publish_service/">Api Publish Service</a></li>
-<li><a href="api_discover_service/">Api Discover Service</a></li>
-<li><a href="api_events_service/">Api Events Service</a></li>
-<li><a href="api_security_service/">Api Security Service</a></li>
-<li><a href="api_logging_service/">Api Logging Service</a></li>
-<li><a href="api_auditing_service/">Api Auditing Service</a></li>
-<li><a href="api_access_control_policy/">Api Access Control Policy</a></li>
-</ul>
-
-
-
-
-
-
-
-
-
-
-
-
-                
-              </article>
-            </div>
-          
-          
-<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
-        </div>
-        
-          <button type="button" class="md-top md-icon" data-md-component="top" hidden>
-  
-  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
-  Back to top
-</button>
-        
-      </main>
-      
-        <footer class="md-footer">
-  
-    
-  
-  <div class="md-footer-meta md-typeset">
-    <div class="md-footer-meta__inner md-grid">
-      <div class="md-copyright">
-  
-    <div class="md-copyright__highlight">
-      Copyright &copy; 2019-2024 TeraflowSDN Project
-    </div>
-  
-  
-    Made with
-    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
-      Material for MkDocs
-    </a>
-  
-</div>
-      
-        <div class="md-social">
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://tfs.etsi.org/" target="_blank" rel="noopener" title="tfs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.4c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64h185.3c2.2 20.4 3.3 41.8 3.3 64m28.8-64h123.1c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64m112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6 78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7 10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5 11.6 26 20.9 58.2 27 94.7m-209 0H18.6c30-74.1 93.6-130.9 172-151.6-25.5 34.2-45.3 87.7-55.3 151.6M8.1 192h123.1c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64m186.6 254.6c-11.6-26-20.9-58.2-27-94.6h176.6c-6.1 36.4-15.5 68.6-27 94.6-10.5 23.6-22.2 40.7-33.5 51.5-11.2 10.7-20.5 13.9-27.8 13.9s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6-78.4-20.7-142-77.5-172-151.6zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6 25.5-34.2 45.2-87.7 55.3-151.6h116.7z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://labs.etsi.org/rep/tfs" target="_blank" rel="noopener" title="labs.etsi.org" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="m503.5 204.6-.7-1.8-69.7-181.78c-1.4-3.57-3.9-6.59-7.2-8.64-2.4-1.55-5.1-2.515-8-2.81s-5.7.083-8.4 1.11c-2.7 1.02-5.1 2.66-7.1 4.78-1.9 2.12-3.3 4.67-4.1 7.44l-47 144H160.8l-47.1-144c-.8-2.77-2.2-5.31-4.1-7.43-2-2.12-4.4-3.75-7.1-4.77a18.1 18.1 0 0 0-8.38-1.113 18.4 18.4 0 0 0-8.04 2.793 18.1 18.1 0 0 0-7.16 8.64L9.267 202.8l-.724 1.8a129.57 129.57 0 0 0-3.52 82c7.747 26.9 24.047 50.7 46.447 67.6l.27.2.59.4 105.97 79.5 52.6 39.7 32 24.2c3.7 1.9 8.3 4.3 13 4.3s9.3-2.4 13-4.3l32-24.2 52.6-39.7 106.7-79.9.3-.3c22.4-16.9 38.7-40.6 45.6-67.5 8.6-27 7.4-55.8-2.6-82"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://www.linkedin.com/company/teraflowsdn/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
-    </a>
-  
-    
-    
-    
-    
-      
-      
-    
-    <a href="https://twitter.com/TeraflowSDN" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
-      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8l164.9-188.5L26.8 48h145.6l100.5 132.9zm-24.8 373.8h39.1L151.1 88h-42z"/></svg>
-    </a>
-  
-</div>
-      
-    </div>
-  </div>
-</footer>
-      
-    </div>
-    <div class="md-dialog" data-md-component="dialog">
-      <div class="md-dialog__inner md-typeset"></div>
-    </div>
-    
-      <div class="md-progress" data-md-component="progress" role="progressbar"></div>
-    
-    
-    <script id="__config" type="application/json">{"base": "../..", "features": ["navigation.instant", "navigation.instant.progress", "navigation.top", "navigation.footer", "navigation.path", "search", "search.highlight", "toc.integrate"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
-    
-    
-      <script src="../../assets/javascripts/bundle.83f73b43.min.js"></script>
-      
-    
-  </body>
-</html>
\ No newline at end of file
-- 
GitLab