diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py index 699208bf19690af438d9faa7faa9a948ab462979..f15d41d6038aadbb0f04583ed40acbc767ff6901 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py @@ -1,24 +1,18 @@ -import connexion -from ..models.service_api_description import ServiceAPIDescription # noqa: E501 from ..core.serviceapidescriptions import PublishServiceOperations +from ..models.service_api_description import ServiceAPIDescription # noqa: E501 -from published_apis.models.problem_details import ProblemDetails # noqa: E501 -from published_apis.models.service_api_description import ServiceAPIDescription # noqa: E501 -from published_apis import util - -from flask import Response, request, current_app +from flask import request, current_app from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps -import asyncio - service_operations = PublishServiceOperations() valid_user = ControlAccess() + def cert_validation(): def _cert_validation(f): @wraps(f) @@ -41,12 +35,18 @@ def cert_validation(): if result is not None: return result + + result = service_operations.check_apf(args["apfId"]) + + if result is not None: + return result result = f(**kwargs) return result return __cert_validation return _cert_validation +# @cert_validation() def apf_id_service_apis_get(apf_id): # noqa: E501 """apf_id_service_apis_get @@ -62,7 +62,7 @@ def apf_id_service_apis_get(apf_id): # noqa: E501 return res - +# @cert_validation() def apf_id_service_apis_post(apf_id, body): # noqa: E501 """apf_id_service_apis_post diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py index efbe3c2d4cf28cec298ef17b394011dcd6aa66cb..641d4029c98c529e454163cec68c7f625f158c15 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py @@ -1,7 +1,8 @@ -from abc import ABC, abstractmethod +from abc import ABC from db.db import MongoDatabse + class Resource(ABC): def __init__(self): - self.db = MongoDatabse() \ No newline at end of file + self.db = MongoDatabse() diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py index c1792b4c7544bd61cf6b5eb73240de1fede51178..165952fff2575a8e49df0750edcf8e2e16057109 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py @@ -18,7 +18,7 @@ service_api_not_found_message = "Service API not found" class PublishServiceOperations(Resource): - def __check_apf(self, apf_id): + def check_apf(self, apf_id): providers_col = self.db.get_col_by_name(self.db.capif_provider_col) current_app.logger.debug("Checking apf id") @@ -49,10 +49,10 @@ class PublishServiceOperations(Resource): current_app.logger.debug("Geting service apis") - result = self.__check_apf(apf_id) + # result = self.__check_apf(apf_id) - if result != None: - return result + # if result != None: + # return result service = mycol.find({"apf_id": apf_id}, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}) @@ -85,10 +85,10 @@ class PublishServiceOperations(Resource): try: current_app.logger.debug("Publishing service") - result = self.__check_apf(apf_id) + # result = self.__check_apf(apf_id) - if result != None: - return result + # if result != None: + # return result service = mycol.find_one( {"api_name": serviceapidescription.api_name}) @@ -144,10 +144,10 @@ class PublishServiceOperations(Resource): try: current_app.logger.debug( "Geting service api with id: " + service_api_id) - result = self.__check_apf(apf_id) + # result = self.__check_apf(apf_id) - if result != None: - return result + # if result != None: + # return result my_query = {'apf_id': apf_id, 'api_id': service_api_id} service_api = mycol.find_one(my_query, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, @@ -176,10 +176,10 @@ class PublishServiceOperations(Resource): current_app.logger.debug( "Removing api service with id: " + service_api_id) - result = self.__check_apf(apf_id) + # result = self.__check_apf(apf_id) - if result != None: - return result + # if result != None: + # return result my_query = {'apf_id': apf_id, 'api_id': service_api_id} serviceapidescription = mycol.find_one(my_query) @@ -217,10 +217,10 @@ class PublishServiceOperations(Resource): current_app.logger.debug( "Updating service api with id: " + service_api_id) - result = self.__check_apf(apf_id) + # result = self.__check_apf(apf_id) - if result != None: - return result + # if result != None: + # return result my_query = {'apf_id': apf_id, 'api_id': service_api_id} serviceapidescription = mycol.find_one(my_query) diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py index 643dda4f7a96c4e663d6aac3fd956ba0797bb39b..3885c5894ec0dde63d0e5f0593a9d35270f5cb22 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py @@ -13,6 +13,13 @@ if monitoring_value == "true": class MongoDatabse(): + # _instance = None + + # def __new__(cls): + # if cls._instance is None: + # cls._instance = super(MongoDatabse, cls).__new__(cls) + # return cls._instance + def __init__(self): self.config = Config().get_config() self.db = self.__connect() @@ -20,7 +27,6 @@ class MongoDatabse(): self.capif_provider_col = self.config['mongo']['capif_provider_col'] self.certs_col = self.config['mongo']['certs_col'] - def get_col_by_name(self, name): return self.db[name].with_options(codec_options=CodecOptions(tz_aware=True)) diff --git a/services/run_capif_tests.sh b/services/run_capif_tests.sh index 3316f187466cd9967fbcb70d8f95f817e1ad4a58..b936f6f0a96d0f70332719cea8193113ebb3a9b4 100755 --- a/services/run_capif_tests.sh +++ b/services/run_capif_tests.sh @@ -18,8 +18,7 @@ CAPIF_HTTPS_PORT=443 # VAULT access configuration CAPIF_VAULT=vault CAPIF_VAULT_PORT=8200 -CAPIF_VAULT_TOKEN=read-ca-token - +CAPIF_VAULT_TOKEN=dev-only-token MOCK_SERVER_URL=http://mock-server:9100 NOTIFICATION_DESTINATION_URL=http://mock-server:9100 diff --git a/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot b/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot index 5df5c4cf29be197ab6f2eed2653e41fb0468648d..7cc95b9a5c1640ca7a6d083951c882bc7d539751 100644 --- a/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot +++ b/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot @@ -324,3 +324,64 @@ Delete APIs Published by NON Authorised apfId ... status=401 ... detail=User not authorized ... cause=Certificate not authorized + + +Retrieve single APIs Published by Authorised apfId TEST + [Tags] capif_api_publish_service-x + # Register APF + ${register_user_info}= Provider Default Registration + + ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api + ... ${register_user_info} + ... service_1 + ${service_api_description_published_2} ${resource_url} ${request_body}= Publish Service Api + ... ${register_user_info} + ... service_2 + + # Store apiId1 + ${serviceApiId1}= Set Variable ${service_api_description_published_1['apiId']} + ${serviceApiId2}= Set Variable ${service_api_description_published_2['apiId']} + + # Retrieve Services 1 + ${resp}= Get Request Capif + ... /published-apis/v1/${register_user_info['apf_id']}/service-apis/${serviceApiId1} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${APF_PROVIDER_USERNAME} + + Check Response Variable Type And Values ${resp} 200 ServiceAPIDescription + Dictionaries Should Be Equal ${resp.json()} ${service_api_description_published_1} + + # Retrieve Services 1 + ${resp}= Get Request Capif + ... /published-apis/v1/${register_user_info['apf_id']}/service-apis/${serviceApiId2} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${APF_PROVIDER_USERNAME} + + Check Response Variable Type And Values ${resp} 200 ServiceAPIDescription + Dictionaries Should Be Equal ${resp.json()} ${service_api_description_published_2} + + ${resp}= Get Request Capif + ... /helper/getServices + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${SUPERADMIN_USERNAME} + + Log Dictionary ${resp.json()} + + ${resp}= Delete Request Capif + ... ${register_user_info['resource_url'].path} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${AMF_PROVIDER_USERNAME} + + Call Method ${CAPIF_USERS} remove_capif_users_entry ${register_user_info['resource_url'].path} + + ${resp}= Get Request Capif + ... /helper/getServices + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${SUPERADMIN_USERNAME} + + Log Dictionary ${resp.json()} diff --git a/tests/features/__init__.robot b/tests/features/__init__.robot index 19e0fdb7e68b094801d11ec7f563450fa5029a0b..3ac73ab8898640e7a1040fe8d9603d55b30fa3c6 100644 --- a/tests/features/__init__.robot +++ b/tests/features/__init__.robot @@ -45,6 +45,8 @@ Prepare environment END # Obtain ca root certificate Retrieve Ca Root + + Retrieve Superadmin Cert Reset Testing Environment @@ -54,3 +56,12 @@ Retrieve Ca Root Status Should Be 200 ${resp} Log ${resp.json()['data']['data']['ca']} Store In File ca.crt ${resp.json()['data']['data']['ca']} + +Retrieve Superadmin Cert + [Documentation] This keyword retrieve ca.root from CAPIF and store it at ca.crt in order to use at TLS communications + ${resp}= Obtain Superadmin Cert From Vault /v1/pki_int/sign/my-ca ${CAPIF_HTTP_VAULT_URL} + Status Should Be 200 ${resp} + Log Dictionary ${resp.json()} + Log ${resp.json()['data']['certificate']} + Store In File ${SUPERADMIN_USERNAME}.crt ${resp.json()['data']['certificate']} + diff --git a/tests/libraries/bodyRequests.py b/tests/libraries/bodyRequests.py index 5e451242c693f385bccea597db898a5f7c16f725..b458689720ee3fa5a1d981a9bd9cd7dca445774b 100644 --- a/tests/libraries/bodyRequests.py +++ b/tests/libraries/bodyRequests.py @@ -5,4 +5,4 @@ from api_publish_service.bodyRequests import * from api_events.bodyRequests import * from security_api.bodyRequests import * from api_provider_management.bodyRequests import * - +from vault_requests.bodyRequests import * diff --git a/tests/libraries/common/bodyRequests.py b/tests/libraries/common/bodyRequests.py index 1d4ec14f60759bfb221b686ba84df23b1386fa6c..c1c3061ab7b9455bbb3d99fb6a403996206b9026 100644 --- a/tests/libraries/common/bodyRequests.py +++ b/tests/libraries/common/bodyRequests.py @@ -1,4 +1,3 @@ -from operator import contains import re import json from xmlrpc.client import boolean @@ -116,6 +115,7 @@ def check_uri(input,rule): else: raise Exception(rule + " is not accomplish rfc3986 rule ("+input+")") + def check_regex(input, regex): matched = re.match(regex, input) is_match = bool(matched) @@ -123,3 +123,13 @@ def check_regex(input, regex): print("Regex match") else: raise Exception("Input(" + input + ") not match regex (" + regex + ")") + + +def vault_sign_superadmin_certificate_body(csr_request): + data = { + 'format': 'pem_bundle', + 'ttl': '43000h', + 'csr': csr_request, + 'common_name': "superadmin" + } + return data diff --git a/tests/libraries/helpers.py b/tests/libraries/helpers.py index c7806f15fa4dc5155495794e009ca8b782dbf06b..1b974f2d743368fe3379e6c3f58f3bda8248e229 100644 --- a/tests/libraries/helpers.py +++ b/tests/libraries/helpers.py @@ -1,13 +1,10 @@ -import requests import re -import pandas as pd from urllib.parse import urlparse from OpenSSL.crypto import (dump_certificate_request, dump_privatekey, PKey, TYPE_RSA, X509Req) from OpenSSL.SSL import FILETYPE_PEM import socket import copy -import json import pickle @@ -142,23 +139,45 @@ def create_scope(aef_id, api_name): return data + def read_dictionary(file_path): with open(file_path, 'rb') as fp: data = pickle.load(fp) print('Dictionary loaded') return data + def write_dictionary(file_path, data): with open(file_path, 'wb') as fp: pickle.dump(data, fp) print('dictionary saved successfully to file ' + file_path) + def filter_users_by_prefix_username(users, prefix): if prefix.strip() == "": raise Exception('prefix value must contain some value') - filtered_users=list() + filtered_users = list() for user in users: if user['username'].startswith(prefix): filtered_users.append(user['username']) return filtered_users + + +def sign_csr_body(username, public_key): + data = { + "csr": public_key.decode("utf-8"), + "mode": "client", + "filename": username + } + return data + + +def vault_sign_superadmin_certificate_body(csr_request): + data = { + "format": "pem_bundle", + "ttl": "43000h", + "csr": csr_request.decode("utf-8"), + "common_name": "superadmin" + } + return data diff --git a/tests/resources/common.resource b/tests/resources/common.resource index 0acd867808cd86832d3ae299cf5f5ada7d7b20d7..d5cc35eb293202e616eceb614aad8083d6089394 100644 --- a/tests/resources/common.resource +++ b/tests/resources/common.resource @@ -8,6 +8,7 @@ Resource /opt/robot-tests/tests/resources/common/basicRequests.robot *** Variables *** +${SUPERADMIN_USERNAME} ROBOT_TESTING_SUPERADMIN ${INVOKER_USERNAME} ROBOT_TESTING_INVOKER ${PROVIDER_USERNAME} ROBOT_TESTING_PROVIDER ${APF_PROVIDER_USERNAME} APF_${PROVIDER_USERNAME} diff --git a/tests/resources/common/basicRequests.robot b/tests/resources/common/basicRequests.robot index 838086f925a9d8310d3e00c55b652c036588b567..9d6b29bc632d69578a1239541a324484f4766afd 100644 --- a/tests/resources/common/basicRequests.robot +++ b/tests/resources/common/basicRequests.robot @@ -6,7 +6,7 @@ Library Collections Library OperatingSystem Library XML Library Telnet -Library String +Library String *** Variables *** @@ -85,7 +85,7 @@ Create Register Admin Session ## NEW REQUESTS TO REGISTER Post Request Admin Register - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${json}=${NONE} @@ -115,7 +115,7 @@ Post Request Admin Register RETURN ${resp} Get Request Admin Register - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${server}=${NONE} @@ -149,7 +149,7 @@ Delete User Admin Register Request # NEW REQUESTS END Post Request Capif - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${json}=${NONE} @@ -179,7 +179,7 @@ Post Request Capif RETURN ${resp} Get Request Capif - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${server}=${NONE} @@ -205,7 +205,7 @@ Get Request Capif RETURN ${resp} Get CA Vault - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${server}=${NONE} @@ -229,10 +229,39 @@ Get CA Vault ... verify=${verify} ... cert=${cert} RETURN ${resp} - RETURN ${response} + +Obtain Superadmin Cert From Vault + [Timeout] ${REQUESTS_TIMEOUT} + [Arguments] + ... ${endpoint} + ... ${server}=${NONE} + ... ${access_token}=${NONE} + ... ${auth}=${NONE} + ... ${verify}=${FALSE} + ... ${cert}=${NONE} + ... ${username}=${NONE} + + ${headers}= Create CAPIF Session ${server} ${access_token} vault_token=${CAPIF_VAULT_TOKEN} + + IF '${username}' != '${NONE}' + ${cert}= Set variable ${{ ('${username}.crt','${username}.key') }} + END + + ${csr_request}= Create User Csr ${SUPERADMIN_USERNAME} cn=superadmin + ${json}= Vault Sign Superadmin Certificate Body ${csr_request} + + ${resp}= Post On Session + ... apisession + ... ${endpoint} + ... json=${json} + ... headers=${headers} + ... expected_status=any + ... verify=${verify} + ... cert=${cert} + RETURN ${resp} Put Request Capif - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${json}=${NONE} @@ -261,7 +290,7 @@ Put Request Capif RETURN ${resp} Patch Request Capif - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${json}=${NONE} @@ -274,7 +303,7 @@ Patch Request Capif ${headers}= Create CAPIF Session ${server} ${access_token} - Set To Dictionary ${headers} Content-Type application/merge-patch+json + Set To Dictionary ${headers} Content-Type application/merge-patch+json IF '${username}' != '${NONE}' ${cert}= Set variable ${{ ('${username}.crt','${username}.key') }} @@ -292,7 +321,7 @@ Patch Request Capif RETURN ${resp} Delete Request Capif - [Timeout] ${REQUESTS_TIMEOUT} + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${server}=${NONE} @@ -439,22 +468,23 @@ Delete User At Register [Documentation] (Administrator) This Keyword delete a user from register. [Arguments] ${username}=${NONE} ${uuid}=${NONE} ${user_uuid}= Set Variable ${uuid} - ${environment_users}= Set Variable ${TRUE} + ${environment_users}= Set Variable ${TRUE} IF "${username}" != "${NONE}" ${user_uuid}= Call Method ${CAPIF_USERS} get_user_uuid ${username} END - IF "${user_uuid}" == "${NONE}" - ${user_uuid}= Get User Uuid At Register ${username} - ${environment_users}= Set Variable ${FALSE} + IF "${user_uuid}" == "${NONE}" + ${user_uuid}= Get User Uuid At Register ${username} + ${environment_users}= Set Variable ${FALSE} END - ${resp}= Delete User Admin Register Request ${user_uuid} + ${resp}= Delete User Admin Register Request ${user_uuid} Should Be Equal As Strings ${resp.status_code} 204 + q - IF ${environment_users} + IF ${environment_users} Call Method ${CAPIF_USERS} remove_register_users_entry ${user_uuid} END @@ -473,23 +503,22 @@ Get List of Users At Register Get User Uuid At Register [Documentation] (Administrator) This Keyword retrieve a list of users and search uuid of user passed by parameters [Arguments] ${username} - ${users}= Get List of Users At Register + ${users}= Get List of Users At Register # Find the first user with username indicated ${user_uuid}= Set Variable &{EMPTY} - FOR ${user} IN @{users} - IF "${user['username']}" == "${username}" - ${user_uuid}= Set Variable ${user['uuid']} + FOR ${user} IN @{users} + IF "${user['username']}" == "${username}" + ${user_uuid}= Set Variable ${user['uuid']} BREAK END END - IF "${user_uuid}" == "${EMPTY}" + IF "${user_uuid}" == "${EMPTY}" Log ${username} not found in Register END - - RETURN ${user_uuid} + RETURN ${user_uuid} Get Auth For User [Documentation] (User) This Keyword retrieve token to be used by user towards first interaction with CCF. @@ -567,7 +596,7 @@ Remove Resource ... verify=ca.crt ... username=${management_cert} - Run Keyword and Continue On Failure Status Should Be 204 ${resp} + Run Keyword and Continue On Failure Status Should Be 204 ${resp} Delete User At Register username=${username} @@ -780,4 +809,3 @@ Create Security Context Between invoker and provider ... username=${register_user_info_invoker['management_cert']} Check Response Variable Type And Values ${resp} 201 ServiceSecurity -