Loading services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py +58 −32 Original line number Diff line number Diff line Loading @@ -3,18 +3,21 @@ from pymongo import ReturnDocument import secrets import requests from .responses import bad_request_error, not_found_error, forbidden_error, internal_server_error, make_response from flask import current_app, Flask, Response from flask import current_app, Response import json from datetime import datetime from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case from ..util import dict_to_camel_case, serialize_clean_camel_case from .auth_manager import AuthManager from .resources import Resource from ..config import Config from api_invoker_management.models.api_invoker_enrolment_details import APIInvokerEnrolmentDetails from .redis_event import RedisEvent from .redis_internal_event import RedisInternalEvent from .publisher import Publisher publisher_ops = Publisher() class InvokerManagementOperations(Resource): def __check_api_invoker_id(self, api_invoker_id): Loading @@ -41,7 +44,8 @@ class InvokerManagementOperations(Resource): 'common_name': invoker_id } response = requests.request("POST", url, headers=headers, data=data, verify = self.config["ca_factory"].get("verify", False)) response = requests.request("POST", url, headers=headers, data=data, verify=self.config["ca_factory"].get("verify", False)) print(response) response_payload = json.loads(response.text) Loading @@ -52,17 +56,18 @@ class InvokerManagementOperations(Resource): self.auth_manager = AuthManager() self.config = Config().get_config() def add_apiinvokerenrolmentdetail(self, apiinvokerenrolmentdetail, username, uuid): mycol = self.db.get_col_by_name(self.db.invoker_enrolment_details) # try: current_app.logger.debug("Creating invoker resource") res = mycol.find_one({'onboarding_information.api_invoker_public_key': apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key}) res = mycol.find_one({'onboarding_information.api_invoker_public_key': apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key}) if res is not None: current_app.logger.error("Generating forbbiden error, invoker registered") current_app.logger.error( "Generating forbbiden error, invoker registered") return forbidden_error(detail="Invoker already registered", cause="Identical invoker public key") if rfc3987.match(apiinvokerenrolmentdetail.notification_destination, rule="URI") is None: Loading @@ -72,11 +77,13 @@ class InvokerManagementOperations(Resource): current_app.logger.debug("Signing Certificate") api_invoker_id = 'INV'+str(secrets.token_hex(15)) cert = self.__sign_cert(apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, api_invoker_id) cert = self.__sign_cert( apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, api_invoker_id) apiinvokerenrolmentdetail.api_invoker_id = api_invoker_id current_app.logger.debug(cert) apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert['data']['certificate'] apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert[ 'data']['certificate'] # Onboarding Date Record invoker_dict = apiinvokerenrolmentdetail.to_dict() Loading @@ -89,14 +96,19 @@ class InvokerManagementOperations(Resource): current_app.logger.debug("Invoker inserted in database") current_app.logger.debug("Netapp onboarded sucessfuly") self.auth_manager.add_auth_invoker(cert['data']['certificate'], api_invoker_id) self.auth_manager.add_auth_invoker( cert['data']['certificate'], api_invoker_id) res = make_response(object=serialize_clean_camel_case(apiinvokerenrolmentdetail), status=201) res.headers['Location'] = "/api-invoker-management/v1/onboardedInvokers/" + str(api_invoker_id) res = make_response(object=serialize_clean_camel_case( apiinvokerenrolmentdetail), status=201) res.headers['Location'] = "/api-invoker-management/v1/onboardedInvokers/" + \ str(api_invoker_id) if res.status_code == 201: current_app.logger.info("Invoker Created") RedisEvent("API_INVOKER_ONBOARDED", ["apiInvokerIds"], [[str(api_invoker_id)]]).send_event() RedisEvent("API_INVOKER_ONBOARDED", ["apiInvokerIds"], [[str(api_invoker_id)]]).send_event() return res def update_apiinvokerenrolmentdetail(self, onboard_id, apiinvokerenrolmentdetail): Loading @@ -111,16 +123,23 @@ class InvokerManagementOperations(Resource): return result if apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key != result["onboarding_information"]["api_invoker_public_key"]: cert = self.__sign_cert(apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, result["api_invoker_id"]) apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert['data']['certificate'] self.auth_manager.update_auth_invoker(cert['data']["certificate"], onboard_id) cert = self.__sign_cert( apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, result["api_invoker_id"]) apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert[ 'data']['certificate'] self.auth_manager.update_auth_invoker( cert['data']["certificate"], onboard_id) apiinvokerenrolmentdetail_update = apiinvokerenrolmentdetail.to_dict() apiinvokerenrolmentdetail_update = { key: value for key, value in apiinvokerenrolmentdetail_update.items() if value is not None } result = mycol.find_one_and_update(result, {"$set":apiinvokerenrolmentdetail_update}, projection={'_id': 0},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(result, {"$set": apiinvokerenrolmentdetail_update}, projection={'_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) result = { key: value for key, value in result.items() if value is not None Loading @@ -130,10 +149,13 @@ class InvokerManagementOperations(Resource): invoker_updated = APIInvokerEnrolmentDetails().from_dict(dict_to_camel_case(result)) res = make_response(object=serialize_clean_camel_case(invoker_updated), status=200) res = make_response(object=serialize_clean_camel_case( invoker_updated), status=200) if res.status_code == 200: current_app.logger.info("Invoker Updated") RedisEvent("API_INVOKER_UPDATED", ["apiInvokerIds"], [[onboard_id]]).send_event() RedisEvent("API_INVOKER_UPDATED", ["apiInvokerIds"], [[onboard_id]]).send_event() return res except Exception as e: Loading @@ -160,13 +182,17 @@ class InvokerManagementOperations(Resource): res = make_response(out, status=204) if res.status_code == 204: current_app.logger.info("Invoker Removed") RedisEvent("API_INVOKER_OFFBOARDED", ["apiInvokerIds"], [[onboard_id]]).send_event() publisher_ops.publish_message("internal-messages", f"invoker-removed:{onboard_id}") RedisEvent("API_INVOKER_OFFBOARDED", ["apiInvokerIds"], [[onboard_id]]).send_event() RedisInternalEvent("INVOKER-REMOVED", "invokerId", { "api_invoker_id": onboard_id }).send_event() return res except Exception as e: exception = "An exception occurred in remove invoker" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/consumer_messager.py +37 −10 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ import redis from .invoker_internal_ops import InvokerInternalOperations from flask import current_app import json class Subscriber(): Loading @@ -14,13 +16,38 @@ class Subscriber(): def listen(self): for raw_message in self.p.listen(): if raw_message["type"] == "message" and raw_message["channel"].decode('utf-8') == "internal-messages": message, invoker_id, api_id = raw_message["data"].decode('utf-8').split(":") if message == "security-context-created": current_app.logger.debug("Internal message received, updating Api list on invoker") self.invoker_ops.update_services_list(invoker_id, api_id) if message == "security-context-removed": current_app.logger.debug("Internal message received, removing service in Api list of invoker") self.invoker_ops.remove_services_list(invoker_id, api_id) current_app.logger.info("New internal event received") internal_redis_event = json.loads( raw_message["data"].decode('utf-8')) if internal_redis_event.get('event') == "SECURITY-CONTEXT-CREATED": current_app.logger.debug( "Internal message received, updating Api list on invoker") security_context_information = internal_redis_event.get( 'information', None) if security_context_information is not None: api_invoker_id = security_context_information.get( 'api_invoker_id') api_id = security_context_information.get('api_id') self.invoker_ops.update_services_list( api_invoker_id, api_id) elif internal_redis_event.get('event') == "SECURITY-CONTEXT-REMOVED": current_app.logger.debug( "Internal message received, removing service in Api list of invoker") security_context_information = internal_redis_event.get( 'information', None) if security_context_information is not None: api_invoker_id = security_context_information.get( 'api_invoker_id') api_id = security_context_information.get('api_id') self.invoker_ops.remove_services_list( api_invoker_id, api_id) elif internal_redis_event.get('event') == "INVOKER-REMOVED": api_invoker_id = internal_redis_event.get( 'information', {"api_invoker_id": None}).get('api_invoker_id') if api_invoker_id is not None: self.acls_ops.remove_invoker_acl(api_invoker_id) elif internal_redis_event.get('event') == "PROVIDER-REMOVED": aef_ids = internal_redis_event.get( 'information', {"aef_ids": []}).get('aef_ids') if len(aef_ids) > 0: self.acls_ops.remove_provider_acls(aef_ids[0]) services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/redis_internal_event.py 0 → 100644 +35 −0 Original line number Diff line number Diff line from ..encoder import JSONEncoder from .publisher import Publisher import json publisher_ops = Publisher() class RedisInternalEvent(): def __init__(self, event, event_detail_key=None, information=None) -> None: self.INTERNAL_MESSAGES = [ 'INVOKER-REMOVED', 'PROVIDER-REMOVED', 'SECURITY-CONTEXT-CREATED', 'SECURITY-CONTEXT-REMOVED', 'create-acl', 'remove-acl', ] if event not in self.INTERNAL_MESSAGES: raise Exception( "Internal Message (" + event + ") is not on INTERNAL_MESSAGES enum (" + ','.join(self.INTERNAL_MESSAGES) + ")") self.redis_event = { "event": event } if event_detail_key is not None and information is not None: self.redis_event['key'] = event_detail_key self.redis_event['information'] = information def to_string(self): return json.dumps(self.redis_event, cls=JSONEncoder) def send_event(self): publisher_ops.publish_message("internal-messages", self.to_string()) def __call__(self): return self.redis_event services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +57 −25 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ from .resources import Resource from .auth_manager import AuthManager from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 from .redis_internal_event import RedisInternalEvent class ProviderManagementOperations(Resource): Loading Loading @@ -40,19 +41,24 @@ class ProviderManagementOperations(Resource): my_provider_enrolment_details = mycol.find_one(search_filter) if my_provider_enrolment_details is not None: current_app.logger.error("Found provider registered with same id") current_app.logger.error( "Found provider registered with same id") return forbidden_error(detail="Provider already registered", cause="Identical provider reg sec") api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex(15) api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex( 15) current_app.logger.debug("Generating certs to api prov funcs") for api_provider_func in api_provider_enrolment_details.api_prov_funcs: api_provider_func.api_prov_func_id = api_provider_func.api_prov_func_role + str(secrets.token_hex(15)) certificate = sign_certificate(api_provider_func.reg_info.api_prov_pub_key, api_provider_func.api_prov_func_id) api_provider_func.api_prov_func_id = api_provider_func.api_prov_func_role + \ str(secrets.token_hex(15)) certificate = sign_certificate( api_provider_func.reg_info.api_prov_pub_key, api_provider_func.api_prov_func_id) api_provider_func.reg_info.api_prov_cert = certificate self.auth_manager.add_auth_provider(certificate, api_provider_func.api_prov_func_id, api_provider_func.api_prov_func_role, api_provider_enrolment_details.api_prov_dom_id) self.auth_manager.add_auth_provider(certificate, api_provider_func.api_prov_func_id, api_provider_func.api_prov_func_role, api_provider_enrolment_details.api_prov_dom_id) # Onboarding Date Record provider_dict = api_provider_enrolment_details.to_dict() Loading @@ -64,9 +70,11 @@ class ProviderManagementOperations(Resource): current_app.logger.debug("Provider inserted in database") res = make_response(object=serialize_clean_camel_case(api_provider_enrolment_details), status=201) res = make_response(object=serialize_clean_camel_case( api_provider_enrolment_details), status=201) res.headers['Location'] = "/api-provider-management/v1/registrations/" + str(api_provider_enrolment_details.api_prov_dom_id) res.headers['Location'] = "/api-provider-management/v1/registrations/" + \ str(api_provider_enrolment_details.api_prov_dom_id) return res except Exception as e: Loading @@ -84,17 +92,32 @@ class ProviderManagementOperations(Resource): if isinstance(result, Response): return result apf_id = [ provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'APF' ] aef_id = [ provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AEF' ] amf_id = [ provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AMF' ] func_ids = list() for provider_func in result["api_prov_funcs"]: func_ids.append(provider_func['api_prov_func_id']) apf_ids = [provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'APF'] aef_ids = [provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AEF'] amf_ids = [provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AMF'] mycol.delete_one({'api_prov_dom_id': api_prov_dom_id}) out = "The provider matching apiProvDomainId " + api_prov_dom_id + " was offboarded." out = "The provider matching apiProvDomainId " + \ api_prov_dom_id + " was offboarded." current_app.logger.debug("Removed provider domain from database") self.auth_manager.remove_auth_provider([apf_id[0], aef_id[0], amf_id[0]]) self.auth_manager.remove_auth_provider(func_ids) RedisInternalEvent("PROVIDER-REMOVED", "providerIds", { "apf_ids": apf_ids, "aef_ids": aef_ids, "amf_ids": amf_ids, "all_ids": apf_ids + aef_ids + amf_ids }).send_event() self.publish_ops.publish_message("internal-messages", f"provider-removed:{aef_id[0]}:{apf_id[0]}:{amf_id[0]}") return make_response(object=out, status=204) except Exception as e: Loading @@ -114,11 +137,14 @@ class ProviderManagementOperations(Resource): for func in api_provider_enrolment_details.api_prov_funcs: if func.api_prov_func_id is None: func.api_prov_func_id = func.api_prov_func_role + str(secrets.token_hex(15)) certificate = sign_certificate(func.reg_info.api_prov_pub_key, func.api_prov_func_id) func.api_prov_func_id = func.api_prov_func_role + \ str(secrets.token_hex(15)) certificate = sign_certificate( func.reg_info.api_prov_pub_key, func.api_prov_func_id) func.reg_info.api_prov_cert = certificate self.auth_manager.update_auth_provider(certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) self.auth_manager.update_auth_provider( certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) else: api_prov_funcs = result["api_prov_funcs"] for api_func in api_prov_funcs: Loading @@ -126,14 +152,18 @@ class ProviderManagementOperations(Resource): if func.api_prov_func_role != api_func["api_prov_func_role"]: return bad_request_error(detail="Bad Role in provider", cause="Different role in update reqeuest", invalid_params=[{"param": "api_prov_func_role", "reason": "different role with same id"}]) if func.reg_info.api_prov_pub_key != api_func["reg_info"]["api_prov_pub_key"]: certificate = sign_certificate(func.reg_info.api_prov_pub_key, api_func["api_prov_func_id"]) certificate = sign_certificate( func.reg_info.api_prov_pub_key, api_func["api_prov_func_id"]) func.reg_info.api_prov_cert = certificate self.auth_manager.update_auth_provider(certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) self.auth_manager.update_auth_provider( certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) api_provider_enrolment_details = api_provider_enrolment_details.to_dict() api_provider_enrolment_details = clean_empty(api_provider_enrolment_details) api_provider_enrolment_details = clean_empty( api_provider_enrolment_details) result = mycol.find_one_and_update(result, {"$set":api_provider_enrolment_details}, projection={'_id': 0},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(result, {"$set": api_provider_enrolment_details}, projection={ '_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) result = clean_empty(result) current_app.logger.debug("Provider domain updated in database") Loading @@ -157,9 +187,11 @@ class ProviderManagementOperations(Resource): return result api_provider_enrolment_details_patch = api_provider_enrolment_details_patch.to_dict() api_provider_enrolment_details_patch = clean_empty(api_provider_enrolment_details_patch) api_provider_enrolment_details_patch = clean_empty( api_provider_enrolment_details_patch) result = mycol.find_one_and_update(result, {"$set":api_provider_enrolment_details_patch}, projection={'_id': 0},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(result, {"$set": api_provider_enrolment_details_patch}, projection={ '_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) result = clean_empty(result) Loading services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/redis_internal_event.py 0 → 100644 +35 −0 Original line number Diff line number Diff line from ..encoder import JSONEncoder from .publisher import Publisher import json publisher_ops = Publisher() class RedisInternalEvent(): def __init__(self, event, event_detail_key=None, information=None) -> None: self.INTERNAL_MESSAGES = [ 'INVOKER-REMOVED', 'PROVIDER-REMOVED', 'SECURITY-CONTEXT-CREATED', 'SECURITY-CONTEXT-REMOVED', 'create-acl', 'remove-acl', ] if event not in self.INTERNAL_MESSAGES: raise Exception( "Internal Message (" + event + ") is not on INTERNAL_MESSAGES enum (" + ','.join(self.INTERNAL_MESSAGES) + ")") self.redis_event = { "event": event } if event_detail_key is not None and information is not None: self.redis_event['key'] = event_detail_key self.redis_event['information'] = information def to_string(self): return json.dumps(self.redis_event, cls=JSONEncoder) def send_event(self): publisher_ops.publish_message("internal-messages", self.to_string()) def __call__(self): return self.redis_event Loading
services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py +58 −32 Original line number Diff line number Diff line Loading @@ -3,18 +3,21 @@ from pymongo import ReturnDocument import secrets import requests from .responses import bad_request_error, not_found_error, forbidden_error, internal_server_error, make_response from flask import current_app, Flask, Response from flask import current_app, Response import json from datetime import datetime from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case from ..util import dict_to_camel_case, serialize_clean_camel_case from .auth_manager import AuthManager from .resources import Resource from ..config import Config from api_invoker_management.models.api_invoker_enrolment_details import APIInvokerEnrolmentDetails from .redis_event import RedisEvent from .redis_internal_event import RedisInternalEvent from .publisher import Publisher publisher_ops = Publisher() class InvokerManagementOperations(Resource): def __check_api_invoker_id(self, api_invoker_id): Loading @@ -41,7 +44,8 @@ class InvokerManagementOperations(Resource): 'common_name': invoker_id } response = requests.request("POST", url, headers=headers, data=data, verify = self.config["ca_factory"].get("verify", False)) response = requests.request("POST", url, headers=headers, data=data, verify=self.config["ca_factory"].get("verify", False)) print(response) response_payload = json.loads(response.text) Loading @@ -52,17 +56,18 @@ class InvokerManagementOperations(Resource): self.auth_manager = AuthManager() self.config = Config().get_config() def add_apiinvokerenrolmentdetail(self, apiinvokerenrolmentdetail, username, uuid): mycol = self.db.get_col_by_name(self.db.invoker_enrolment_details) # try: current_app.logger.debug("Creating invoker resource") res = mycol.find_one({'onboarding_information.api_invoker_public_key': apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key}) res = mycol.find_one({'onboarding_information.api_invoker_public_key': apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key}) if res is not None: current_app.logger.error("Generating forbbiden error, invoker registered") current_app.logger.error( "Generating forbbiden error, invoker registered") return forbidden_error(detail="Invoker already registered", cause="Identical invoker public key") if rfc3987.match(apiinvokerenrolmentdetail.notification_destination, rule="URI") is None: Loading @@ -72,11 +77,13 @@ class InvokerManagementOperations(Resource): current_app.logger.debug("Signing Certificate") api_invoker_id = 'INV'+str(secrets.token_hex(15)) cert = self.__sign_cert(apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, api_invoker_id) cert = self.__sign_cert( apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, api_invoker_id) apiinvokerenrolmentdetail.api_invoker_id = api_invoker_id current_app.logger.debug(cert) apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert['data']['certificate'] apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert[ 'data']['certificate'] # Onboarding Date Record invoker_dict = apiinvokerenrolmentdetail.to_dict() Loading @@ -89,14 +96,19 @@ class InvokerManagementOperations(Resource): current_app.logger.debug("Invoker inserted in database") current_app.logger.debug("Netapp onboarded sucessfuly") self.auth_manager.add_auth_invoker(cert['data']['certificate'], api_invoker_id) self.auth_manager.add_auth_invoker( cert['data']['certificate'], api_invoker_id) res = make_response(object=serialize_clean_camel_case(apiinvokerenrolmentdetail), status=201) res.headers['Location'] = "/api-invoker-management/v1/onboardedInvokers/" + str(api_invoker_id) res = make_response(object=serialize_clean_camel_case( apiinvokerenrolmentdetail), status=201) res.headers['Location'] = "/api-invoker-management/v1/onboardedInvokers/" + \ str(api_invoker_id) if res.status_code == 201: current_app.logger.info("Invoker Created") RedisEvent("API_INVOKER_ONBOARDED", ["apiInvokerIds"], [[str(api_invoker_id)]]).send_event() RedisEvent("API_INVOKER_ONBOARDED", ["apiInvokerIds"], [[str(api_invoker_id)]]).send_event() return res def update_apiinvokerenrolmentdetail(self, onboard_id, apiinvokerenrolmentdetail): Loading @@ -111,16 +123,23 @@ class InvokerManagementOperations(Resource): return result if apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key != result["onboarding_information"]["api_invoker_public_key"]: cert = self.__sign_cert(apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, result["api_invoker_id"]) apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert['data']['certificate'] self.auth_manager.update_auth_invoker(cert['data']["certificate"], onboard_id) cert = self.__sign_cert( apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, result["api_invoker_id"]) apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert[ 'data']['certificate'] self.auth_manager.update_auth_invoker( cert['data']["certificate"], onboard_id) apiinvokerenrolmentdetail_update = apiinvokerenrolmentdetail.to_dict() apiinvokerenrolmentdetail_update = { key: value for key, value in apiinvokerenrolmentdetail_update.items() if value is not None } result = mycol.find_one_and_update(result, {"$set":apiinvokerenrolmentdetail_update}, projection={'_id': 0},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(result, {"$set": apiinvokerenrolmentdetail_update}, projection={'_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) result = { key: value for key, value in result.items() if value is not None Loading @@ -130,10 +149,13 @@ class InvokerManagementOperations(Resource): invoker_updated = APIInvokerEnrolmentDetails().from_dict(dict_to_camel_case(result)) res = make_response(object=serialize_clean_camel_case(invoker_updated), status=200) res = make_response(object=serialize_clean_camel_case( invoker_updated), status=200) if res.status_code == 200: current_app.logger.info("Invoker Updated") RedisEvent("API_INVOKER_UPDATED", ["apiInvokerIds"], [[onboard_id]]).send_event() RedisEvent("API_INVOKER_UPDATED", ["apiInvokerIds"], [[onboard_id]]).send_event() return res except Exception as e: Loading @@ -160,13 +182,17 @@ class InvokerManagementOperations(Resource): res = make_response(out, status=204) if res.status_code == 204: current_app.logger.info("Invoker Removed") RedisEvent("API_INVOKER_OFFBOARDED", ["apiInvokerIds"], [[onboard_id]]).send_event() publisher_ops.publish_message("internal-messages", f"invoker-removed:{onboard_id}") RedisEvent("API_INVOKER_OFFBOARDED", ["apiInvokerIds"], [[onboard_id]]).send_event() RedisInternalEvent("INVOKER-REMOVED", "invokerId", { "api_invoker_id": onboard_id }).send_event() return res except Exception as e: exception = "An exception occurred in remove invoker" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e))
services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/consumer_messager.py +37 −10 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ import redis from .invoker_internal_ops import InvokerInternalOperations from flask import current_app import json class Subscriber(): Loading @@ -14,13 +16,38 @@ class Subscriber(): def listen(self): for raw_message in self.p.listen(): if raw_message["type"] == "message" and raw_message["channel"].decode('utf-8') == "internal-messages": message, invoker_id, api_id = raw_message["data"].decode('utf-8').split(":") if message == "security-context-created": current_app.logger.debug("Internal message received, updating Api list on invoker") self.invoker_ops.update_services_list(invoker_id, api_id) if message == "security-context-removed": current_app.logger.debug("Internal message received, removing service in Api list of invoker") self.invoker_ops.remove_services_list(invoker_id, api_id) current_app.logger.info("New internal event received") internal_redis_event = json.loads( raw_message["data"].decode('utf-8')) if internal_redis_event.get('event') == "SECURITY-CONTEXT-CREATED": current_app.logger.debug( "Internal message received, updating Api list on invoker") security_context_information = internal_redis_event.get( 'information', None) if security_context_information is not None: api_invoker_id = security_context_information.get( 'api_invoker_id') api_id = security_context_information.get('api_id') self.invoker_ops.update_services_list( api_invoker_id, api_id) elif internal_redis_event.get('event') == "SECURITY-CONTEXT-REMOVED": current_app.logger.debug( "Internal message received, removing service in Api list of invoker") security_context_information = internal_redis_event.get( 'information', None) if security_context_information is not None: api_invoker_id = security_context_information.get( 'api_invoker_id') api_id = security_context_information.get('api_id') self.invoker_ops.remove_services_list( api_invoker_id, api_id) elif internal_redis_event.get('event') == "INVOKER-REMOVED": api_invoker_id = internal_redis_event.get( 'information', {"api_invoker_id": None}).get('api_invoker_id') if api_invoker_id is not None: self.acls_ops.remove_invoker_acl(api_invoker_id) elif internal_redis_event.get('event') == "PROVIDER-REMOVED": aef_ids = internal_redis_event.get( 'information', {"aef_ids": []}).get('aef_ids') if len(aef_ids) > 0: self.acls_ops.remove_provider_acls(aef_ids[0])
services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/redis_internal_event.py 0 → 100644 +35 −0 Original line number Diff line number Diff line from ..encoder import JSONEncoder from .publisher import Publisher import json publisher_ops = Publisher() class RedisInternalEvent(): def __init__(self, event, event_detail_key=None, information=None) -> None: self.INTERNAL_MESSAGES = [ 'INVOKER-REMOVED', 'PROVIDER-REMOVED', 'SECURITY-CONTEXT-CREATED', 'SECURITY-CONTEXT-REMOVED', 'create-acl', 'remove-acl', ] if event not in self.INTERNAL_MESSAGES: raise Exception( "Internal Message (" + event + ") is not on INTERNAL_MESSAGES enum (" + ','.join(self.INTERNAL_MESSAGES) + ")") self.redis_event = { "event": event } if event_detail_key is not None and information is not None: self.redis_event['key'] = event_detail_key self.redis_event['information'] = information def to_string(self): return json.dumps(self.redis_event, cls=JSONEncoder) def send_event(self): publisher_ops.publish_message("internal-messages", self.to_string()) def __call__(self): return self.redis_event
services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +57 −25 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ from .resources import Resource from .auth_manager import AuthManager from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 from .redis_internal_event import RedisInternalEvent class ProviderManagementOperations(Resource): Loading Loading @@ -40,19 +41,24 @@ class ProviderManagementOperations(Resource): my_provider_enrolment_details = mycol.find_one(search_filter) if my_provider_enrolment_details is not None: current_app.logger.error("Found provider registered with same id") current_app.logger.error( "Found provider registered with same id") return forbidden_error(detail="Provider already registered", cause="Identical provider reg sec") api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex(15) api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex( 15) current_app.logger.debug("Generating certs to api prov funcs") for api_provider_func in api_provider_enrolment_details.api_prov_funcs: api_provider_func.api_prov_func_id = api_provider_func.api_prov_func_role + str(secrets.token_hex(15)) certificate = sign_certificate(api_provider_func.reg_info.api_prov_pub_key, api_provider_func.api_prov_func_id) api_provider_func.api_prov_func_id = api_provider_func.api_prov_func_role + \ str(secrets.token_hex(15)) certificate = sign_certificate( api_provider_func.reg_info.api_prov_pub_key, api_provider_func.api_prov_func_id) api_provider_func.reg_info.api_prov_cert = certificate self.auth_manager.add_auth_provider(certificate, api_provider_func.api_prov_func_id, api_provider_func.api_prov_func_role, api_provider_enrolment_details.api_prov_dom_id) self.auth_manager.add_auth_provider(certificate, api_provider_func.api_prov_func_id, api_provider_func.api_prov_func_role, api_provider_enrolment_details.api_prov_dom_id) # Onboarding Date Record provider_dict = api_provider_enrolment_details.to_dict() Loading @@ -64,9 +70,11 @@ class ProviderManagementOperations(Resource): current_app.logger.debug("Provider inserted in database") res = make_response(object=serialize_clean_camel_case(api_provider_enrolment_details), status=201) res = make_response(object=serialize_clean_camel_case( api_provider_enrolment_details), status=201) res.headers['Location'] = "/api-provider-management/v1/registrations/" + str(api_provider_enrolment_details.api_prov_dom_id) res.headers['Location'] = "/api-provider-management/v1/registrations/" + \ str(api_provider_enrolment_details.api_prov_dom_id) return res except Exception as e: Loading @@ -84,17 +92,32 @@ class ProviderManagementOperations(Resource): if isinstance(result, Response): return result apf_id = [ provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'APF' ] aef_id = [ provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AEF' ] amf_id = [ provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AMF' ] func_ids = list() for provider_func in result["api_prov_funcs"]: func_ids.append(provider_func['api_prov_func_id']) apf_ids = [provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'APF'] aef_ids = [provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AEF'] amf_ids = [provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AMF'] mycol.delete_one({'api_prov_dom_id': api_prov_dom_id}) out = "The provider matching apiProvDomainId " + api_prov_dom_id + " was offboarded." out = "The provider matching apiProvDomainId " + \ api_prov_dom_id + " was offboarded." current_app.logger.debug("Removed provider domain from database") self.auth_manager.remove_auth_provider([apf_id[0], aef_id[0], amf_id[0]]) self.auth_manager.remove_auth_provider(func_ids) RedisInternalEvent("PROVIDER-REMOVED", "providerIds", { "apf_ids": apf_ids, "aef_ids": aef_ids, "amf_ids": amf_ids, "all_ids": apf_ids + aef_ids + amf_ids }).send_event() self.publish_ops.publish_message("internal-messages", f"provider-removed:{aef_id[0]}:{apf_id[0]}:{amf_id[0]}") return make_response(object=out, status=204) except Exception as e: Loading @@ -114,11 +137,14 @@ class ProviderManagementOperations(Resource): for func in api_provider_enrolment_details.api_prov_funcs: if func.api_prov_func_id is None: func.api_prov_func_id = func.api_prov_func_role + str(secrets.token_hex(15)) certificate = sign_certificate(func.reg_info.api_prov_pub_key, func.api_prov_func_id) func.api_prov_func_id = func.api_prov_func_role + \ str(secrets.token_hex(15)) certificate = sign_certificate( func.reg_info.api_prov_pub_key, func.api_prov_func_id) func.reg_info.api_prov_cert = certificate self.auth_manager.update_auth_provider(certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) self.auth_manager.update_auth_provider( certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) else: api_prov_funcs = result["api_prov_funcs"] for api_func in api_prov_funcs: Loading @@ -126,14 +152,18 @@ class ProviderManagementOperations(Resource): if func.api_prov_func_role != api_func["api_prov_func_role"]: return bad_request_error(detail="Bad Role in provider", cause="Different role in update reqeuest", invalid_params=[{"param": "api_prov_func_role", "reason": "different role with same id"}]) if func.reg_info.api_prov_pub_key != api_func["reg_info"]["api_prov_pub_key"]: certificate = sign_certificate(func.reg_info.api_prov_pub_key, api_func["api_prov_func_id"]) certificate = sign_certificate( func.reg_info.api_prov_pub_key, api_func["api_prov_func_id"]) func.reg_info.api_prov_cert = certificate self.auth_manager.update_auth_provider(certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) self.auth_manager.update_auth_provider( certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) api_provider_enrolment_details = api_provider_enrolment_details.to_dict() api_provider_enrolment_details = clean_empty(api_provider_enrolment_details) api_provider_enrolment_details = clean_empty( api_provider_enrolment_details) result = mycol.find_one_and_update(result, {"$set":api_provider_enrolment_details}, projection={'_id': 0},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(result, {"$set": api_provider_enrolment_details}, projection={ '_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) result = clean_empty(result) current_app.logger.debug("Provider domain updated in database") Loading @@ -157,9 +187,11 @@ class ProviderManagementOperations(Resource): return result api_provider_enrolment_details_patch = api_provider_enrolment_details_patch.to_dict() api_provider_enrolment_details_patch = clean_empty(api_provider_enrolment_details_patch) api_provider_enrolment_details_patch = clean_empty( api_provider_enrolment_details_patch) result = mycol.find_one_and_update(result, {"$set":api_provider_enrolment_details_patch}, projection={'_id': 0},return_document=ReturnDocument.AFTER ,upsert=False) result = mycol.find_one_and_update(result, {"$set": api_provider_enrolment_details_patch}, projection={ '_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) result = clean_empty(result) Loading
services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/redis_internal_event.py 0 → 100644 +35 −0 Original line number Diff line number Diff line from ..encoder import JSONEncoder from .publisher import Publisher import json publisher_ops = Publisher() class RedisInternalEvent(): def __init__(self, event, event_detail_key=None, information=None) -> None: self.INTERNAL_MESSAGES = [ 'INVOKER-REMOVED', 'PROVIDER-REMOVED', 'SECURITY-CONTEXT-CREATED', 'SECURITY-CONTEXT-REMOVED', 'create-acl', 'remove-acl', ] if event not in self.INTERNAL_MESSAGES: raise Exception( "Internal Message (" + event + ") is not on INTERNAL_MESSAGES enum (" + ','.join(self.INTERNAL_MESSAGES) + ")") self.redis_event = { "event": event } if event_detail_key is not None and information is not None: self.redis_event['key'] = event_detail_key self.redis_event['information'] = information def to_string(self): return json.dumps(self.redis_event, cls=JSONEncoder) def send_event(self): publisher_ops.publish_message("internal-messages", self.to_string()) def __call__(self): return self.redis_event