diff --git a/.gitignore b/.gitignore index ec4110f6bcb0b1b03185416bfc8c62a9f7f5cb70..651e1692f9c36007ca84ddbef9050d047a091be3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,8 +36,5 @@ docs/testing_with_postman/package-lock.json results helm/capif/*.lock -<<<<<<< HEAD helm/capif/charts -======= helm/capif/charts/tempo* ->>>>>>> staging diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__main__.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/app.py similarity index 93% rename from services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__main__.py rename to services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/app.py index 32ccc2eb015def617c98d798aa9ba55adf04cbd2..a85597dcd2119dfb44f955d47fdd07ec5afc4e42 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__main__.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/app.py @@ -2,13 +2,10 @@ import connexion import logging -from api_invoker_management import encoder - -from flask import Flask, jsonify, request +import encoder from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient -from .config import Config -from .core.consumer_messager import Subscriber +from config import Config +from core.consumer_messager import Subscriber from logging.handlers import RotatingFileHandler import os from fluent import sender @@ -23,12 +20,6 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - -import sys -import uuid - - - NAME = "Invoker-Service" def configure_monitoring(app, config): @@ -144,9 +135,4 @@ subscriber = Subscriber() @app.app.before_first_request def create_listener_message(): - executor.submit(subscriber.listen) - -if __name__ == '__main__': - import logging - app.run(debug=True, port=8080) - + executor.submit(subscriber.listen) \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py index 12c217cfd224b92362eb86e4713e47f5882f1bcc..9ea3c42833a20adcf5d6ef598fc17de3efdfd644 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py @@ -1,14 +1,11 @@ import connexion -from api_invoker_management.models.api_invoker_enrolment_details import APIInvokerEnrolmentDetails # noqa: E501 +from ..models.api_invoker_enrolment_details import APIInvokerEnrolmentDetails # noqa: E501 from ..core.apiinvokerenrolmentdetails import InvokerManagementOperations from ..core.validate_user import ControlAccess -import json from flask import Response, request, current_app from flask_jwt_extended import jwt_required, get_jwt_identity -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.publisher import Publisher diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py index 3a8ec3ffe2787f220ac90e4ef7906a41a800789e..3c3c38bdcc8f19bcf05deb7573e2a1f40110ccee 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py @@ -6,7 +6,7 @@ from .responses import bad_request_error, not_found_error, forbidden_error, inte from flask import current_app, Flask, Response import json from datetime import datetime -from ..util import dict_to_camel_case +from ..util import dict_to_camel_case, clean_empty from .auth_manager import AuthManager from .resources import Resource from ..config import Config @@ -74,7 +74,6 @@ class InvokerManagementOperations(Resource): api_invoker_id = 'INV'+str(secrets.token_hex(15)) 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'] @@ -92,7 +91,7 @@ class InvokerManagementOperations(Resource): self.auth_manager.add_auth_invoker(cert['data']['certificate'], api_invoker_id) - res = make_response(object=apiinvokerenrolmentdetail, status=201) + res = make_response(object=dict_to_camel_case(clean_empty(apiinvokerenrolmentdetail.to_dict())), status=201) res.headers['Location'] = "/api-invoker-management/v1/onboardedInvokers/" + str(api_invoker_id) if res.status_code == 201: @@ -134,7 +133,9 @@ class InvokerManagementOperations(Resource): current_app.logger.debug("Invoker Resource inserted in database") - res = make_response(object=APIInvokerEnrolmentDetails().from_dict(dict_to_camel_case(result)), status=200) + invoker_updated = APIInvokerEnrolmentDetails().from_dict(dict_to_camel_case(result)) + + res = make_response(object=dict_to_camel_case(clean_empty(invoker_updated.to_dict())), status=200) if res.status_code == 200: current_app.logger.info("Invoker Updated") RedisEvent("API_INVOKER_UPDATED", "apiInvokerIds", [onboard_id]).send_event() diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py index cfab01e271b46df831399394a92ce54732ff8003..c3736a6d4e2e95d58ab6a96c1e62fe42404538f1 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py @@ -1,5 +1,3 @@ - -from flask import current_app from cryptography import x509 from cryptography.hazmat.backends import default_backend from .resources import Resource diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py index a0aa138a0d9c63b49446b4fa04c93e6afde3d03a..a680d4d53205846ed11e6723b553138877c564d8 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py @@ -1,6 +1,5 @@ from .resources import Resource -from flask import current_app class InvokerInternalOperations(Resource): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py index 3898c4b8309b14a05f8b5de89626fac8ebea4fc4..34fcdf453873b4b59a894d9f6b96b7ce1a217c2e 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py @@ -1,6 +1,4 @@ import redis -import sys -from flask import current_app class Publisher(): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py index 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..96ace13619f80f897251bf57a4ad2f9dfb1b755b 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py @@ -2,6 +2,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response import json +from ..util import dict_to_camel_case, clean_empty mimetype = "application/json" @@ -13,19 +14,35 @@ def make_response(object, status): def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py index 5a2a5dc560b1a7a6c2a62791ded0792da4746a90..bcf0d880f669fa3a298c08da63df17f58213d2ec 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py @@ -4,6 +4,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import dict_to_camel_case, clean_empty + class ControlAccess(Resource): @@ -18,6 +20,9 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py index 638cc80e7f1b8e2e5e8e50165f4100fce5383920..6cb5a93bca3e130f884139e55951259ee7cb412a 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py @@ -1,8 +1,7 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py index 04b06eb0adb09b675ccd98384aa98fc9fabbbe2c..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from api_invoker_management.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py index 6ce55d89b6a2673f6ad15702c9335d578877825e..27ba971d63477ec583e6c0fe54097c652daab757 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py @@ -1,8 +1,20 @@ import datetime import six -import typing -from api_invoker_management import typing_utils +import typing_utils + + +def clean_empty(d): + if isinstance(d, dict): + return { + k: v + for k, v in ((k, clean_empty(v)) for k, v in d.items()) + if v + } + if isinstance(d, list): + return [v for v in map(clean_empty, d) if v] + return d + def dict_to_camel_case(my_dict): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/wsgi.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh b/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh index 90ce2be086ecaa87740728f0f1f32c10627b0c1e..df73fa6481be279fa52e2d825b529024f1f36bff 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh @@ -14,5 +14,5 @@ curl -vv -k -retry 30 \ --request GET "$VAULT_ADDR/v1/secret/data/server_cert/pub" 2>/dev/null | jq -r '.data.data.pub_key' -j > /usr/src/app/api_invoker_management/pubkey.pem -cd /usr/src/app/ -python3 -m api_invoker_management \ No newline at end of file +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/api_invoker_management wsgi:app \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt b/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt index ce843e66061b4a6627a867b9853ce81adb411441..10f300b8eb9f0ed04ef0b6a98f16796a0f1db207 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt @@ -19,3 +19,5 @@ fluent-logger == 0.10.0 opentelemetry-api == 1.19.0 opentelemetry-sdk == 1.19.0 flask_executor == 1.0.0 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__main__.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/app.py similarity index 81% rename from services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__main__.py rename to services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/app.py index f52d69c40eaa4612ea6069b5226490ec95c17fc2..37692057f86f0d0900039edd99576dfcca7e4863 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__main__.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/app.py @@ -3,14 +3,13 @@ import connexion import logging -from api_provider_management import encoder +import encoder from flask_jwt_extended import JWTManager from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config import os import sys from fluent import sender -from flask_executor import Executor from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry import trace from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator @@ -106,31 +105,23 @@ def verbose_formatter(): datefmt='%d/%m/%Y %H:%M:%S' ) -def main(): - with open("/usr/src/app/api_provider_management/pubkey.pem", "rb") as pub_file: - pub_data = pub_file.read() +with open("/usr/src/app/api_provider_management/pubkey.pem", "rb") as pub_file: + pub_data = pub_file.read() - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'CAPIF_API_Provider_Management_API'}, - pythonic_params=True) +app = connexion.App(__name__, specification_dir='./openapi/') +app.app.json_encoder = encoder.JSONEncoder +app.add_api('openapi.yaml', + arguments={'title': 'CAPIF_API_Provider_Management_API'}, + pythonic_params=True) - config = Config() - configure_logging(app.app) +config = Config() +configure_logging(app.app) - if eval(os.environ.get("MONITORING").lower().capitalize()): - configure_monitoring(app.app, config.get_config()) +if eval(os.environ.get("MONITORING").lower().capitalize()): + configure_monitoring(app.app, config.get_config()) - app.app.config['JWT_ALGORITHM'] = 'RS256' - app.app.config['JWT_PUBLIC_KEY'] = pub_data +app.app.config['JWT_ALGORITHM'] = 'RS256' +app.app.config['JWT_PUBLIC_KEY'] = pub_data - JWTManager(app.app) - - - app.run(port=8080, debug=True) - - -if __name__ == '__main__': - main() +JWTManager(app.app) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py index 377b14f8c368cebf98409223d089fc31326d1987..bed212ac136607ee7459f333b0f50bf7f3481b6b 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime if stamp != self.cached: diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py index f5bcf167319a5d29255b0b2c688c2e3ab60f460f..d9a190cd5cd48ceca8fcb7c8ecea79bc5c173b29 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py @@ -1,19 +1,18 @@ import connexion -import six -import json - from flask import Response, request, current_app + from ..core.provider_enrolment_details_api import ProviderManagementOperations -from ..encoder import JSONEncoder -from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 -from api_provider_management.models.problem_details import ProblemDetails # noqa: E501 -from api_provider_management import util +from ..models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 +from ..models.problem_details import ProblemDetails # noqa: E501 +from .. import util +from ..core.validate_user import ControlAccess + from cryptography import x509 from cryptography.hazmat.backends import default_backend from flask_jwt_extended import jwt_required, get_jwt_identity from cryptography import x509 from functools import wraps -from ..core.validate_user import ControlAccess + import sys diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py index dde822bbfbd9a8099bf4f7dcc9f84dfc7f57a2ad..dee8d1539b8945e2ff049a9ad8afb5dc4a0c34c9 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py @@ -1,15 +1,12 @@ -from email.quoprimime import body_decode import connexion -import six -import json - from flask import Response, request, current_app from ..core.provider_enrolment_details_api import ProviderManagementOperations from ..encoder import JSONEncoder -from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 -from api_provider_management.models.api_provider_enrolment_details_patch import APIProviderEnrolmentDetailsPatch # noqa: E501 -from api_provider_management.models.problem_details import ProblemDetails # noqa: E501 -from api_provider_management import util +from ..models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 +from ..models.api_provider_enrolment_details_patch import APIProviderEnrolmentDetailsPatch # noqa: E501 +from ..models.problem_details import ProblemDetails # noqa: E501 +from .. import util + from cryptography.hazmat.backends import default_backend from cryptography import x509 diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py index a4a2d2419926d281426ce7876f4d45c1165fed40..cfa302ada519fbe9116b2bc33cae39ddeb009f87 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py @@ -1,5 +1,4 @@ -from flask import current_app from cryptography import x509 from cryptography.hazmat.backends import default_backend from .resources import Resource diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 399ac7457f971397966d7385f5ad2702babc338e..0b54ee8152e85552bd99c5d64560498e67e69721 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -45,7 +45,7 @@ class ProviderManagementOperations(Resource): api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex(15) - current_app.logger.debug("Geretaing certs to api prov funcs") + 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)) @@ -64,7 +64,8 @@ class ProviderManagementOperations(Resource): current_app.logger.debug("Provider inserted in database") - res = make_response(object=api_provider_enrolment_details, status=201) + res = make_response(object=dict_to_camel_case(api_provider_enrolment_details.to_dict()), status=201) + res.headers['Location'] = "/api-provider-management/v1/registrations/" + str(api_provider_enrolment_details.api_prov_dom_id) return res @@ -123,22 +124,21 @@ class ProviderManagementOperations(Resource): for api_func in api_prov_funcs: if func.api_prov_func_id == api_func["api_prov_func_id"]: 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":"differente role with same id"}]) + 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"]) 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) - api_provider_enrolment_details = api_provider_enrolment_details.to_dict() 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 = clean_empty(result) current_app.logger.debug("Provider domain updated in database") - return make_response(object=APIProviderEnrolmentDetails().from_dict(dict_to_camel_case(result)), status=200) + provider_updated = APIProviderEnrolmentDetails().from_dict(dict_to_camel_case(result)) + return make_response(object=dict_to_camel_case(provider_updated.to_dict()), status=200) except Exception as e: exception = "An exception occurred in update provider" @@ -163,8 +163,8 @@ class ProviderManagementOperations(Resource): result = clean_empty(result) current_app.logger.debug("Provider domain updated in database") - - return make_response(object=APIProviderEnrolmentDetails().from_dict(dict_to_camel_case(result)), status=200) + provider_updated = APIProviderEnrolmentDetails().from_dict(dict_to_camel_case(result)) + return make_response(object=dict_to_camel_case(provider_updated.to_dict()), status=200) except Exception as e: exception = "An exception occurred in patch provider" diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py index 38d7259fbf3480e808cd67c3f25f965a5ffcdba4..acedb7e3e337fda548faf59c1a1b240a4ca6f905 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py @@ -1,5 +1,4 @@ import redis -import sys class Publisher(): diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py index 86e99d4bfcd5811fcc9256cfdb82839266dbd8b5..7b8092ab35ed7214a6eddfdad30577747e3a673a 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py @@ -1,6 +1,6 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse -from .publisher import Publisher +from abc import ABC +from db.db import MongoDatabse +from core.publisher import Publisher class Resource(ABC): diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..4ad6bb852aa030e61f7c9e21d1ba80ec1866dbee 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py @@ -1,31 +1,49 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder -from flask import Response +from ..util import dict_to_camel_case, clean_empty +from flask import Response, current_app import json mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) - return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + prob = prob.to_dict() + prob = clean_empty(prob) + + return Response(json.dumps(dict_to_camel_case(prob), cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) - return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + prob = prob.to_dict() + prob = clean_empty(prob) + + return Response(json.dumps(dict_to_camel_case(prob), cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) - return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + + return Response(json.dumps(dict_to_camel_case(prob), cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) - return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file + prob = prob.to_dict() + prob = clean_empty(prob) + + return Response(json.dumps(dict_to_camel_case(prob), cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py index 6ec96cf181ad21ebcbeec3247a34b17da559e214..159947e476ac184261ecb2f48f3d952537ee0ce9 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py @@ -1,6 +1,5 @@ import requests import json -import sys from ..config import Config def sign_certificate(publick_key, provider_id): diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py index 4d101aee06bd0e3a763f8727c7bdb2f9a09caa61..4a9445dcac121dd9c073cab1bd3cca64e4e849b8 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py @@ -4,6 +4,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import dict_to_camel_case, clean_empty class ControlAccess(Resource): @@ -18,6 +19,9 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py index a67e2ea8412dedb818ce8352e7d91357c55a590d..fcc6169db2432423538a7ea2dbf07ca0b3f3824c 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py @@ -1,8 +1,7 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py index 01531f242309ec381907e92bba20d3cf9f01306d..3f1c01ce6812b1ff12e0d1d284bc433e951e1ea6 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py @@ -1,8 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from api_provider_management.models.base_model_ import Model - +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): include_nulls = False diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py index e769d2852d772e8716895c7c9313987f4e44bf74..6fc44d5dbab0b9106f0531b8296b0197f8f927ff 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py @@ -1,8 +1,6 @@ import datetime - import six -import typing -from api_provider_management import typing_utils +import typing_utils def clean_empty(d): if isinstance(d, dict): diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/wsgi.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh b/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh index 93bf420144dcbd0fdfb40055dc94104d9e63d07b..5ec3096850c15a6a5ec6f9ad7173e61a122baf97 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh +++ b/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh @@ -13,7 +13,7 @@ curl -vv -k -retry 30 \ --request GET "$VAULT_ADDR/v1/secret/data/server_cert/pub" 2>/dev/null | jq -r '.data.data.pub_key' -j > /usr/src/app/api_provider_management/pubkey.pem +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/api_provider_management wsgi:app -cd /usr/src/app/ -python3 -m api_provider_management diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt b/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt index d45d1e529f471f976ba4d88f0141be29bc38a4be..c93b338e3de87e1e1261088d59a122d5c38d8c29 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt +++ b/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt @@ -18,4 +18,5 @@ fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 - +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile b/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile index 92dcb338cb2592781871d50a47f69796ab664f41..c69bd56afa7c975dd03c3f83115145b076594dd1 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile @@ -11,6 +11,6 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] +ENTRYPOINT ["gunicorn"] -CMD ["-m", "openapi_server"] \ No newline at end of file +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/capif_acl", "wsgi:app"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/__init__.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__init__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/__init__.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__main__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/app.py similarity index 94% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__main__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/app.py index 215e85efe43a80a28bd8ac8bb3875498ced1bcd0..344df6b7ff0ea76a7014ec411948ba9ed31cc9a6 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__main__.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/app.py @@ -2,19 +2,17 @@ import connexion -from openapi_server import encoder +import encoder import logging -from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config from datetime import datetime import os from fluent import sender -from .core.consumer_messager import Subscriber +from core.consumer_messager import Subscriber from flask_executor import Executor from flask_apscheduler import APScheduler from opentelemetry.instrumentation.flask import FlaskInstrumentor @@ -117,11 +115,8 @@ app.add_api('openapi.yaml', arguments={'title': 'CAPIF_Access_Control_policy_API'}, pythonic_params=True) - config = Config() - - jwt = JWTManager(app.app) configure_logging(app.app) @@ -138,12 +133,9 @@ subscriber = Subscriber() scheduler = APScheduler() scheduler.api_enabled = True scheduler.init_app(app.app) +scheduler.start() @scheduler.task('date', id='listener', next_run_time=datetime.now()) def up_listener(): with scheduler.app.app_context(): executor.submit(subscriber.listen()) - -if __name__ == '__main__': - scheduler.start() - app.run(debug=True,port=8080, use_reloader=False) diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/config.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/config.py similarity index 92% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/config.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/config.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/__init__.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/__init__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/__init__.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/default_controller.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/default_controller.py similarity index 98% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/default_controller.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/default_controller.py index c17e19585710f78c4374eb50e1cafa2070973432..eb047f064d5012bd8fc5743ff0e4d358ca075298 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/default_controller.py @@ -1,4 +1,4 @@ -from typing import Dict + from functools import wraps from flask import request, current_app from cryptography import x509 @@ -6,6 +6,7 @@ from cryptography.hazmat.backends import default_backend from ..core.accesscontrolpolicyapi import accessControlPolicyApi + def cert_validation(): def _cert_validation(f): @wraps(f) diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/security_controller_.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/security_controller_.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/security_controller_.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/security_controller_.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/accesscontrolpolicyapi.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/accesscontrolpolicyapi.py similarity index 98% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/accesscontrolpolicyapi.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/accesscontrolpolicyapi.py index f644caef07f1ffb72d8ed4fc5492f37ebf97e14e..d82ac984b04e746ad372a3e0574a67e50a77d88f 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/accesscontrolpolicyapi.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/accesscontrolpolicyapi.py @@ -4,6 +4,7 @@ from .responses import make_response, not_found_error, internal_server_error from ..models.access_control_policy_list import AccessControlPolicyList from ..util import dict_to_camel_case, clean_empty + class accessControlPolicyApi(Resource): def get_acl(self, service_api_id, aef_id, api_invoker_id, supported_features): @@ -45,7 +46,7 @@ class accessControlPolicyApi(Resource): return not_found_error(f"No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}", "Wrong id") acl = AccessControlPolicyList(api_invoker_policies) - response = acl.to_dict() + response = clean_empty(acl.to_dict()) return make_response(object=dict_to_camel_case(response), status=200) except Exception as e: diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/consumer_messager.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/consumer_messager.py similarity index 98% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/consumer_messager.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/consumer_messager.py index 72c51eeacdbf45668cde55141e17a4ad87db0e09..0da24408e801f22693e0412636df090680c1424c 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/consumer_messager.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/consumer_messager.py @@ -1,6 +1,6 @@ # subscriber.py import redis -from ..config import Config +from config import Config from .internal_service_ops import InternalServiceOps from flask import current_app diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/internal_service_ops.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py similarity index 96% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/internal_service_ops.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py index 26a7d53795a41899aa2ff4726a80685fcdc01db2..1e5aa20c0d708dee31e51b2586e0295ba3ea629a 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/internal_service_ops.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py @@ -1,11 +1,12 @@ from flask import current_app from .resources import Resource -from ..models.api_invoker_policy import ApiInvokerPolicy -from ..models.time_range_list import TimeRangeList +from models.api_invoker_policy import ApiInvokerPolicy +from models.time_range_list import TimeRangeList from datetime import datetime, timedelta + from .redis_event import RedisEvent -from ..util import dict_to_camel_case, clean_empty +from util import dict_to_camel_case, clean_empty class InternalServiceOps(Resource): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/publisher.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/publisher.py similarity index 83% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/publisher.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/publisher.py index 3898c4b8309b14a05f8b5de89626fac8ebea4fc4..8292de4d4330b14c17be74e7448403b56fc5b9e3 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/publisher.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/publisher.py @@ -1,6 +1,5 @@ import redis -import sys -from flask import current_app + class Publisher(): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/redis_event.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/redis_event.py similarity index 97% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/redis_event.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/redis_event.py index aadbdbb6b3116cf288648de41effdb12b9ca9143..40e3e406830e58a72359e4283d8ff6e0d66bb893 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/redis_event.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/redis_event.py @@ -1,4 +1,4 @@ -from ..encoder import JSONEncoder +from encoder import JSONEncoder from .publisher import Publisher import json diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/resources.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/resources.py new file mode 100644 index 0000000000000000000000000000000000000000..d5a3552d6b3459a77d30df65d0bbda4a86c7fa61 --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/resources.py @@ -0,0 +1,8 @@ +from abc import ABC +from db.db import MongoDatabse + + +class Resource(ABC): + + def __init__(self): + self.db = MongoDatabse() \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/responses.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/responses.py similarity index 72% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/responses.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..9d5ea092050de02f5813149bde790f9becaa3c90 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/responses.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/responses.py @@ -1,31 +1,53 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import dict_to_camel_case, clean_empty import json mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/db/db.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/db/db.py similarity index 97% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/db/db.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/db/db.py index b25c794b7699a6a904946e15810795825edb5ff5..d1185c2d34134104a5daa57938ab29c628db2f00 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/db/db.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/db/db.py @@ -1,8 +1,8 @@ -import atexit + import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/encoder.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/encoder.py similarity index 91% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/encoder.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/encoder.py index 3bbef854f3b83dc985aea885756fd7147fa00001..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/encoder.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from openapi_server.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4c4e60f91034863564e2c69f9c75a1d883d6990d --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/__init__.py @@ -0,0 +1,10 @@ +# coding: utf-8 + +# flake8: noqa +from __future__ import absolute_import +# import models into model package +from capif_acl.models.access_control_policy_list import AccessControlPolicyList +from capif_acl.models.api_invoker_policy import ApiInvokerPolicy +from capif_acl.models.invalid_param import InvalidParam +from capif_acl.models.problem_details import ProblemDetails +from capif_acl.models.time_range_list import TimeRangeList diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/access_control_policy_list.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/access_control_policy_list.py similarity index 90% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/access_control_policy_list.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/access_control_policy_list.py index 98f3fc122323f37a2868acd21375c3a6870b6970..b3cacd4164aab94158436597b462dc967f91a2f7 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/access_control_policy_list.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/access_control_policy_list.py @@ -5,11 +5,11 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server.models.api_invoker_policy import ApiInvokerPolicy -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl.models.api_invoker_policy import ApiInvokerPolicy +from capif_acl import util -from openapi_server.models.api_invoker_policy import ApiInvokerPolicy # noqa: E501 +from capif_acl.models.api_invoker_policy import ApiInvokerPolicy # noqa: E501 class AccessControlPolicyList(Model): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/api_invoker_policy.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/api_invoker_policy.py similarity index 96% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/api_invoker_policy.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/api_invoker_policy.py index a5f1b477c384bd485981ea49ab09ffb793796b1d..86ffec0cf84c8c867ebbd8db1594eb2746140591 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/api_invoker_policy.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/api_invoker_policy.py @@ -5,11 +5,11 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server.models.time_range_list import TimeRangeList -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl.models.time_range_list import TimeRangeList +from capif_acl import util -from openapi_server.models.time_range_list import TimeRangeList # noqa: E501 +from capif_acl.models.time_range_list import TimeRangeList # noqa: E501 class ApiInvokerPolicy(Model): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/base_model_.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/base_model_.py similarity index 98% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/base_model_.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/base_model_.py index 916e582ec27f19e7dbbb65885786760d5e7e4e98..cce5379c767ede112d5fdcdcffa34403bddb2884 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/base_model_.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/base_model_.py @@ -3,7 +3,7 @@ import pprint import six import typing -from openapi_server import util +from capif_acl import util T = typing.TypeVar('T') diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/invalid_param.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/invalid_param.py similarity index 96% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/invalid_param.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/invalid_param.py index 8d91e6c3f6dfe46c67a864916c0f8cd282d41f81..88606c4107c7ac4b408a0548af2feb398233b555 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/invalid_param.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/invalid_param.py @@ -5,8 +5,8 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl import util class InvalidParam(Model): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/problem_details.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/problem_details.py similarity index 97% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/problem_details.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/problem_details.py index 08f2908c2964db647b8f890d2931f08dfceafeff..25caab4e29a65d9df08d966a551618c69a2ffa45 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/problem_details.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/problem_details.py @@ -5,12 +5,12 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server.models.invalid_param import InvalidParam +from capif_acl.models.base_model_ import Model +from capif_acl.models.invalid_param import InvalidParam import re -from openapi_server import util +from capif_acl import util -from openapi_server.models.invalid_param import InvalidParam # noqa: E501 +from capif_acl.models.invalid_param import InvalidParam # noqa: E501 import re # noqa: E501 class ProblemDetails(Model): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/time_range_list.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/time_range_list.py similarity index 96% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/time_range_list.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/time_range_list.py index eb18a7ed915166f82490460850cf108c384397c8..eaacad60592ff7acf1a9c2b7b71c21dfb6fd5083 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/time_range_list.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/time_range_list.py @@ -5,8 +5,8 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl import util class TimeRangeList(Model): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/openapi/openapi.yaml b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/openapi/openapi.yaml similarity index 99% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/openapi/openapi.yaml rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/openapi/openapi.yaml index 6f8c99d300bdb9b5224f8164f2c38e160c513699..1621baa9a449be7d8bb2377e7b2b6fd590cbec5d 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/openapi/openapi.yaml +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/openapi/openapi.yaml @@ -130,7 +130,7 @@ paths: description: Service Unavailable default: description: Generic Error - x-openapi-router-controller: openapi_server.controllers.default_controller + x-openapi-router-controller: capif_acl.controllers.default_controller components: responses: "307": diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/__init__.py similarity index 89% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/__init__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/__init__.py index 364aba9fbf880b8a6d2d011380bd092f2e5d973a..5d664f823dc74e062cbb804324de82bf7d239643 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/__init__.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/__init__.py @@ -3,7 +3,7 @@ import logging import connexion from flask_testing import TestCase -from openapi_server.encoder import JSONEncoder +from capif_acl.encoder import JSONEncoder class BaseTestCase(TestCase): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/test_default_controller.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/test_default_controller.py similarity index 79% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/test_default_controller.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/test_default_controller.py index c850757e5ca3b3f1d5aa5ed6349b8ce22fb4186d..44ed0bee14671018ffb842dfe7e98edf26875ec2 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/test_default_controller.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/test_default_controller.py @@ -3,12 +3,7 @@ from __future__ import absolute_import import unittest -from flask import json -from six import BytesIO - -from openapi_server.models.access_control_policy_list import AccessControlPolicyList # noqa: E501 -from openapi_server.models.problem_details import ProblemDetails # noqa: E501 -from openapi_server.test import BaseTestCase +from test import BaseTestCase class TestDefaultController(BaseTestCase): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/typing_utils.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/typing_utils.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/typing_utils.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/typing_utils.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/util.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/util.py similarity index 98% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/util.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/util.py index 672406d079a400d7d50956c018539f2d5c95e370..27903905e56c3a50fd6e8ee7ca314a931e2e494e 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/util.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/util.py @@ -1,8 +1,8 @@ import datetime import six -import typing -from openapi_server import typing_utils +import typing_utils + def clean_empty(d): if isinstance(d, dict): @@ -15,6 +15,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): @@ -41,8 +42,6 @@ def dict_to_camel_case(my_dict): return result - - def _deserialize(data, klass): """Deserializes dict, list, str into an object. diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/wsgi.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/resources.py b/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/resources.py deleted file mode 100644 index 94e29ec07359c93a78d520f24fa91c88971d65c4..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/resources.py +++ /dev/null @@ -1,7 +0,0 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse - -class Resource(ABC): - - def __init__(self): - self.db = MongoDatabse() \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/__init__.py deleted file mode 100644 index a4269de2a23336ebf21fb6fe2813f1bc573459d0..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# coding: utf-8 - -# flake8: noqa -from __future__ import absolute_import -# import models into model package -from openapi_server.models.access_control_policy_list import AccessControlPolicyList -from openapi_server.models.api_invoker_policy import ApiInvokerPolicy -from openapi_server.models.invalid_param import InvalidParam -from openapi_server.models.problem_details import ProblemDetails -from openapi_server.models.time_range_list import TimeRangeList diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt b/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt index 03d8aafa8f87a0cfeeeddc14cb5ccc8a81c7ea83..087fc12410d50fa32f5acf232478cc220e921adf 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt @@ -27,3 +27,5 @@ redis == 4.5.4 flask_executor == 1.0.0 Flask-APScheduler == 1.12.4 Flask-Script == 2.0.6 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Auditing_API/Dockerfile b/services/TS29222_CAPIF_Auditing_API/Dockerfile index d7030b67013b0e43402f59ff7374a52c099a6b9d..4908c19cbc4b57479053a5f908561f10da17d7eb 100644 --- a/services/TS29222_CAPIF_Auditing_API/Dockerfile +++ b/services/TS29222_CAPIF_Auditing_API/Dockerfile @@ -12,6 +12,6 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] +ENTRYPOINT ["gunicorn"] -CMD ["-m", "logs"] \ No newline at end of file +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/logs", "wsgi:app"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Auditing_API/logs/__main__.py b/services/TS29222_CAPIF_Auditing_API/logs/app.py similarity index 97% rename from services/TS29222_CAPIF_Auditing_API/logs/__main__.py rename to services/TS29222_CAPIF_Auditing_API/logs/app.py index 385f0b589919612de7fc19c5315fea86f73d6e05..9a94d5ad140cba523740852a36f10ae518dc7ccb 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/__main__.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/app.py @@ -3,8 +3,8 @@ import connexion import logging from logging.handlers import RotatingFileHandler -from logs import encoder -from .config import Config +import encoder +from config import Config import os from fluent import sender from opentelemetry.instrumentation.flask import FlaskInstrumentor @@ -111,6 +111,3 @@ configure_logging(app.app) config = Config() if eval(os.environ.get("MONITORING").lower().capitalize()): configure_monitoring(app.app, config.get_config()) - -if __name__ == '__main__': - app.run(port=8080) diff --git a/services/TS29222_CAPIF_Auditing_API/logs/config.py b/services/TS29222_CAPIF_Auditing_API/logs/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/config.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py b/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py index c330f47dcf64184d10590cbf343373a19c255099..ead9ec5341d13bf3150ad460f174c3c91e714f3c 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py @@ -1,21 +1,8 @@ -import connexion -import six -import sys - -from logs.models.interface_description import InterfaceDescription # noqa: E501 -from logs.models.invocation_log import InvocationLog # noqa: E501 -from logs.models.operation import Operation # noqa: E501 -from logs.models.problem_details import ProblemDetails # noqa: E501 -from logs.models.protocol import Protocol # noqa: E501 -from logs import util +from ..util import deserialize_datetime from ..core.auditoperations import AuditOperations -import json from flask import Response, request, current_app -from ..encoder import JSONEncoder -from cryptography import x509 -from cryptography.hazmat.backends import default_backend -import pymongo + from ..core.responses import bad_request_error audit_operations = AuditOperations() @@ -65,8 +52,8 @@ def api_invocation_logs_get(aef_id=None, api_invoker_id=None, time_range_start=N cause="Mandatory parameters missing", invalid_params=[ {"param": "aef_id or api_invoker_id", "reason": "missing"}]) - time_range_start = util.deserialize_datetime(time_range_start) - time_range_end = util.deserialize_datetime(time_range_end) + time_range_start = deserialize_datetime(time_range_start) + time_range_end = deserialize_datetime(time_range_end) query_params = {"aef_id": aef_id, "api_invoker_id": api_invoker_id, diff --git a/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py b/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py index ac83701ce453c122e8445e41d808b9d658fd3928..6632d2808e8ec3f82bf19ff9a2a947dc1b6de2c6 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py @@ -1,11 +1,9 @@ -import sys from flask import current_app, Flask, Response import json -import sys -from datetime import datetime + from .resources import Resource -from bson import json_util + from ..util import dict_to_camel_case, clean_empty from .responses import bad_request_error, not_found_error, forbidden_error, internal_server_error, make_response from ..models.invocation_log import InvocationLog @@ -57,11 +55,9 @@ class AuditOperations (Resource): if not result['logs']: return not_found_error(detail="Parameters do not match any log entry", cause="No logs found") - - result = dict_to_camel_case(clean_empty(result)) - invocation_log = InvocationLog(result['aefId'], result['apiInvokerId'], result['logs'], - result['supportedFeatures']) - res = make_response(object=invocation_log, status=200) + invocation_log = InvocationLog(result['aef_id'], result['api_invoker_id'], result['logs'], + result['supported_features']) + res = make_response(object=dict_to_camel_case(clean_empty(invocation_log.to_dict())), status=200) current_app.logger.debug("Found invocation logs") return res diff --git a/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py b/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py index d55b30c74cf87bf22eec115dfc1bd0e6d413a018..d5a3552d6b3459a77d30df65d0bbda4a86c7fa61 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py @@ -1,5 +1,5 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from abc import ABC +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py b/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py index 5986c5000910cc9c0f0d579051db9477f5943c17..9d5ea092050de02f5813149bde790f9becaa3c90 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py @@ -1,6 +1,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import dict_to_camel_case, clean_empty import json mimetype = "application/json" @@ -15,22 +16,38 @@ def make_response(object, status): def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Auditing_API/logs/db/db.py b/services/TS29222_CAPIF_Auditing_API/logs/db/db.py index f3286d22125674dd3cbd9cc5b8dccc2dba73f25c..17a93fe7e254ad1192a95b7fe0300c4384a31623 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/db/db.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/db/db.py @@ -1,9 +1,8 @@ -import atexit + import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config -from bson.codec_options import CodecOptions +from config import Config import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_Auditing_API/logs/encoder.py b/services/TS29222_CAPIF_Auditing_API/logs/encoder.py index 55259f5fafc566e72cad147c9f1fada83c2d5130..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/encoder.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from logs.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Auditing_API/logs/util.py b/services/TS29222_CAPIF_Auditing_API/logs/util.py index ff812577975f62d6488f6ebc71bbed8492b7c0d3..ec1430110f5a167f67a8c083cfda84af63a678d4 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/util.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/util.py @@ -1,8 +1,8 @@ import datetime import six -import typing -from logs import typing_utils +import typing_utils + def clean_empty(d): if isinstance(d, dict): @@ -15,6 +15,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): diff --git a/services/TS29222_CAPIF_Auditing_API/logs/wsgi.py b/services/TS29222_CAPIF_Auditing_API/logs/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Auditing_API/logs/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Auditing_API/requirements.txt b/services/TS29222_CAPIF_Auditing_API/requirements.txt index 197399ff21107a2e3f2edc6519445c38b38de335..cb1e43905a79b1fdcbe01282175cd884eb958efa 100644 --- a/services/TS29222_CAPIF_Auditing_API/requirements.txt +++ b/services/TS29222_CAPIF_Auditing_API/requirements.txt @@ -18,3 +18,5 @@ opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 pyopenssl == 23.0.0 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Discover_Service_API/Dockerfile b/services/TS29222_CAPIF_Discover_Service_API/Dockerfile index efa70c90c56f5e1cb49d14f0c551f2ce04a924e0..9f1d46ea6ee674e69b958e111488d41b7013028d 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/Dockerfile +++ b/services/TS29222_CAPIF_Discover_Service_API/Dockerfile @@ -12,6 +12,6 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] +ENTRYPOINT ["gunicorn"] -CMD ["-m", "service_apis"] \ No newline at end of file +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/service_apis", "wsgi:app"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Discover_Service_API/requirements.txt b/services/TS29222_CAPIF_Discover_Service_API/requirements.txt index 33a22f4690946e965ae42ce289caff1fb2c707ac..1732b50d295c03701cf7001b7c96b917d79a655e 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/requirements.txt +++ b/services/TS29222_CAPIF_Discover_Service_API/requirements.txt @@ -19,4 +19,6 @@ fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 -flask_executor == 1.0.0 \ No newline at end of file +flask_executor == 1.0.0 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/__main__.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/app.py similarity index 94% rename from services/TS29222_CAPIF_Discover_Service_API/service_apis/__main__.py rename to services/TS29222_CAPIF_Discover_Service_API/service_apis/app.py index 57326e94c3687e466735d998c4c7da75b64509a8..d3cbec7019c0cacefc299ca0099e21fc4cc061ec 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/__main__.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/app.py @@ -2,18 +2,15 @@ import connexion -from service_apis import encoder +import encoder -import pymongo import logging -from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config + import os from fluent import sender -from flask_executor import Executor from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry import trace from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter @@ -23,10 +20,9 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - - NAME = "Discover-Service" + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -125,7 +121,3 @@ if eval(os.environ.get("MONITORING").lower().capitalize()): configure_monitoring(app.app, config.get_config()) jwt = JWTManager(app.app) - - -if __name__ == '__main__': - app.run(debug=True, port=8080) diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py index aef2022efcf54738587431c9a84a38b43a8dcc09..2c81a78e019e640b140dbde5f6463f7784502ee2 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py @@ -1,13 +1,6 @@ -import sys -from service_apis.core.discoveredapis import DiscoverApisOperations -import json +from ..core.discoveredapis import DiscoverApisOperations from flask import Response, request, current_app -from service_apis.encoder import JSONEncoder -from service_apis.models.problem_details import ProblemDetails -from cryptography import x509 -from cryptography.hazmat.backends import default_backend -import pymongo discover_apis = DiscoverApisOperations() diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py index f56b5851bbbf4862d10f4f4bf32aa72ba05daaee..9ad5462dfb1ae4ea1d2fb46851b6d8cc04959962 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py @@ -1,18 +1,9 @@ -import sys -import pymongo from flask import current_app, Flask, Response -import json -from service_apis.core.responses import internal_server_error, forbidden_error ,make_response, not_found_error -from service_apis.db.db import MongoDatabse -from service_apis.encoder import JSONEncoder -from service_apis.models.problem_details import ProblemDetails -from service_apis.models.service_api_description import ServiceAPIDescription -from service_apis.models.discovered_apis import DiscoveredAPIs -from service_apis.util import dict_to_camel_case, clean_empty -from service_apis.core.resources import Resource -from bson import json_util - +from ..core.responses import internal_server_error, forbidden_error ,make_response, not_found_error +from ..models.discovered_apis import DiscoveredAPIs +from ..util import dict_to_camel_case, clean_empty +from ..core.resources import Resource class DiscoverApisOperations(Resource): @@ -46,16 +37,13 @@ class DiscoverApisOperations(Resource): discoved_apis = services.find(my_query, {"_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}) json_docs = [] for discoved_api in discoved_apis: - my_api = dict_to_camel_case(discoved_api) - my_api = clean_empty(my_api) - json_docs.append(my_api) + json_docs.append(discoved_api) if len(json_docs) == 0: return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions") apis_discoveres = DiscoveredAPIs(service_api_descriptions=json_docs) - res = make_response(object=apis_discoveres, status=200) - current_app.logger.debug("Discovered APIs by: " + api_invoker_id) + res = make_response(object=dict_to_camel_case(clean_empty(apis_discoveres.to_dict())), status=200) return res except Exception as e: diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py index 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py index 4f035781f68629246ade764083b620e3df3c72ae..df9905f96f4eaa990334d30c8b99fd58521cd28a 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py @@ -1,7 +1,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response -from bson import json_util +from ..util import dict_to_camel_case, clean_empty import json mimetype = "application/json" @@ -14,19 +14,35 @@ def make_response(object, status): def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py index 544545555ff393d3c2b43e825f3595af7df97bfd..2b259ceadf253f8530d7097f3bb53bf934bb312e 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py @@ -1,8 +1,7 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor @@ -10,6 +9,7 @@ from opentelemetry.instrumentation.pymongo import PymongoInstrumentor if eval(os.environ.get("MONITORING").lower().capitalize()): PymongoInstrumentor().instrument() + class MongoDatabse(): def __init__(self): diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py index c02675977bb308223c728bfbb3a393fb99c5a588..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from service_apis.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py index b3f89d7add5037cf33a17d3c717e8295080d8a8b..c39e5fabe5806ecc746990ca002cbedb72676827 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py @@ -1,9 +1,7 @@ import datetime -import sys import six -import typing -from service_apis import typing_utils +import typing_utils def clean_empty(d): if isinstance(d, dict): @@ -27,6 +25,8 @@ def dict_to_camel_case(my_dict): my_key= ''.join([my_key[0].lower(), my_key[1:]]) if my_key == "serviceApiCategory": my_key = "serviceAPICategory" + elif my_key == "serviceApiDescriptions": + my_key = "serviceAPIDescriptions" if isinstance(value, list): result[my_key] = list(map( diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/wsgi.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Events_API/Dockerfile b/services/TS29222_CAPIF_Events_API/Dockerfile index ddcf2da935752d7eb90aa1dd59c2eb5811eaf5e0..1fef3f2ede15e1de5674980d38a35fbbeebb6c7b 100644 --- a/services/TS29222_CAPIF_Events_API/Dockerfile +++ b/services/TS29222_CAPIF_Events_API/Dockerfile @@ -13,6 +13,6 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] +ENTRYPOINT ["gunicorn"] -CMD ["-m", "capif_events"] \ No newline at end of file +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/capif_events", "wsgi:app"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Events_API/capif_events/__main__.py b/services/TS29222_CAPIF_Events_API/capif_events/app.py similarity index 95% rename from services/TS29222_CAPIF_Events_API/capif_events/__main__.py rename to services/TS29222_CAPIF_Events_API/capif_events/app.py index 1e602ef80d3468f980ce3c9b19d455cfeee1f285..ead8b5288edadaa94c078a7f410af31a31430f2e 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/__main__.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/app.py @@ -4,21 +4,21 @@ import connexion import sys import logging -from capif_events import encoder +import encoder from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token from pymongo import MongoClient -from .config import Config -from .core.notifications import Notifications -from .core.consumer_messager import Subscriber + +from core.notifications import Notifications +from core.consumer_messager import Subscriber from multiprocessing import Process from threading import Thread from flask_executor import Executor from flask_apscheduler import APScheduler from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config import os from fluent import sender from flask_executor import Executor @@ -32,7 +32,6 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - NAME = "Events-Service" def configure_monitoring(app, config): @@ -146,6 +145,3 @@ subscriber = Subscriber() @app.app.before_first_request def create_listener_message(): executor.submit(subscriber.listen) - -if __name__ == '__main__': - app.run(debug=True, port=8080) diff --git a/services/TS29222_CAPIF_Events_API/capif_events/config.py b/services/TS29222_CAPIF_Events_API/capif_events/config.py index 377b14f8c368cebf98409223d089fc31326d1987..bed212ac136607ee7459f333b0f50bf7f3481b6b 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/config.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime if stamp != self.cached: diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py b/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py index 1ece644c124fcf17b47f8aaea59ab4c67c1b0e86..d6b5bdff29dcec3161150bd42b8c24b62636633b 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py @@ -12,7 +12,7 @@ from .resources import Resource from bson import json_util from .responses import internal_server_error, not_found_error, make_response, bad_request_error from ..db.db import MongoDatabse -from ..util import dict_to_camel_case +from ..util import dict_to_camel_case, clean_empty from .auth_manager import AuthManager class EventSubscriptionsOperations(Resource): @@ -73,7 +73,7 @@ class EventSubscriptionsOperations(Resource): self.auth_manager.add_auth_event(subscription_id, subscriber_id) - res = make_response(object=event_subscription, status=201) + res = make_response(object=dict_to_camel_case(clean_empty(event_subscription.to_dict())), status=201) res.headers['Location'] = "http://localhost:8080/capif-events/v1/" + \ str(subscriber_id) + "/subscriptions/" + str(subscription_id) diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py b/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py index 2229a7182fadb59adec89bac65565dc5affe4bea..3b32d1106838fd9760afa1c4dedd2b5fc378d0db 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py @@ -1,15 +1,16 @@ #import concurrent import requests from .internal_event_ops import InternalEventOperations -from ..models.event_notification import EventNotification -from ..models.access_control_policy_list_ext import AccessControlPolicyListExt -from ..models.capif_event_detail import CAPIFEventDetail -from ..encoder import JSONEncoder +from models.event_notification import EventNotification +from models.access_control_policy_list_ext import AccessControlPolicyListExt +from models.capif_event_detail import CAPIFEventDetail +from encoder import JSONEncoder import sys import json from flask import current_app import asyncio import aiohttp +from util import dict_to_camel_case, clean_empty class Notifications(): @@ -33,9 +34,9 @@ class Notifications(): event_detail={redis_event.get('key'):redis_event.get('information')} current_app.logger.debug(event_detail) data = EventNotification(sub["subscription_id"], events=redis_event.get('event'), event_detail=event_detail) - current_app.logger.debug(json.dumps(data,cls=JSONEncoder)) + current_app.logger.debug(json.dumps(data.to_dict(),cls=JSONEncoder)) - asyncio.run(self.send(url, json.loads(json.dumps(data,cls=JSONEncoder)))) + asyncio.run(self.send(url, dict_to_camel_case(clean_empty(data.to_dict())))) except Exception as e: current_app.logger.error("An exception occurred ::" + str(e)) diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py b/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py index 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py b/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..7862390ddb6ad27d60a0e9a1d2e4f358111f2270 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py @@ -1,6 +1,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import dict_to_camel_case, clean_empty import json mimetype = "application/json" @@ -13,19 +14,35 @@ def make_response(object, status): def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py b/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py index 18d54a2ec108ecd87483cf0c314e52c8eb6fad6c..be87defb5d803bd80211c83f13a25c8d8fd53ec9 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py @@ -4,6 +4,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import dict_to_camel_case, clean_empty class ControlAccess(Resource): @@ -18,6 +19,11 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature or "event_subscriptions" not in cert_entry["resources"] or event_id not in cert_entry["resources"]["event_subscriptions"]: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_Events_API/capif_events/db/db.py b/services/TS29222_CAPIF_Events_API/capif_events/db/db.py index 2f4d1190297508fd9b49946fc193ba92b6e2d99e..c68c8098fdb1a0139c1053fad19f2584c60bd856 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/db/db.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/db/db.py @@ -2,7 +2,7 @@ import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_Events_API/capif_events/encoder.py b/services/TS29222_CAPIF_Events_API/capif_events/encoder.py index f6b018f22f8e92eb3c919f4cb4546d61a550fcd0..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/encoder.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from capif_events.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Events_API/capif_events/util.py b/services/TS29222_CAPIF_Events_API/capif_events/util.py index 396c6a5b258c051cf1c86b93d2bf79e998463ace..f067fde2be418e00a062b17852b3f051171ea4ef 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/util.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/util.py @@ -2,32 +2,39 @@ import datetime import six import typing -from capif_events import typing_utils +import typing_utils -def dict_to_camel_case(my_dict): +def clean_empty(d): + if isinstance(d, dict): + return { + k: v + for k, v in ((k, clean_empty(v)) for k, v in d.items()) + if v is not None or v == 0 + } + if isinstance(d, list): + return [v for v in map(clean_empty, d) if v is not None or v == 0] + return d +def dict_to_camel_case(my_dict): result = {} - for attr, value in my_dict.items(): - - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) - + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key= ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr if isinstance(value, list): result[my_key] = list(map( lambda x: dict_to_camel_case(x) if isinstance(x, dict) else x, value )) - elif hasattr(value, "to_dict"): result[my_key] = dict_to_camel_case(value) - elif isinstance(value, dict): value = dict_to_camel_case(value) result[my_key] = value else: result[my_key] = value - return result diff --git a/services/TS29222_CAPIF_Events_API/capif_events/wsgi.py b/services/TS29222_CAPIF_Events_API/capif_events/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Events_API/capif_events/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Events_API/requirements.txt b/services/TS29222_CAPIF_Events_API/requirements.txt index 743f814afa711b0c66d3236a0875642335eedd99..8cc1fc1c02bd25ce5c4782ce9ca3a284f4c55ee8 100644 --- a/services/TS29222_CAPIF_Events_API/requirements.txt +++ b/services/TS29222_CAPIF_Events_API/requirements.txt @@ -23,3 +23,5 @@ flask_executor Flask-APScheduler aiohttp==3.9.5 async-timeout==4.0.3 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile b/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile index 7339cecd74384864a4d4414b579e0dbc012e6b1c..4248907cc2319d8bf85ae446f9e9d77c1ea3be80 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile @@ -12,6 +12,6 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] +ENTRYPOINT ["gunicorn"] -CMD ["-m", "api_invocation_logs"] \ No newline at end of file +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/api_invocation_logs", "wsgi:app"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__main__.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/app.py similarity index 97% rename from services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__main__.py rename to services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/app.py index f5323c9ef96c6ffeb29dcdb8e932859a7d1f64d0..e7b839742c0c2584df24bd6bcb9c384e0c5d3566 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__main__.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/app.py @@ -3,8 +3,8 @@ import connexion import logging from logging.handlers import RotatingFileHandler -from api_invocation_logs import encoder -from .config import Config +import encoder +from config import Config import os from fluent import sender from opentelemetry.instrumentation.flask import FlaskInstrumentor @@ -16,10 +16,9 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor - - NAME = "Logging-Service" + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -115,6 +114,3 @@ config = Config() if eval(os.environ.get("MONITORING").lower().capitalize()): configure_monitoring(app.app, config.get_config()) - -if __name__ == '__main__': - app.run(port=8080) diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py index eb0cd986a51c521efd0f201c10cb529f65e45d51..7ce9972710b904bdd045e6ca7525f0e46785fa06 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py @@ -1,13 +1,11 @@ import connexion -from api_invocation_logs.models.invocation_log import InvocationLog # noqa: E501 +from ..models.invocation_log import InvocationLog # noqa: E501 from ..core.invocationlogs import LoggingInvocationOperations -import json from flask import Response, request, current_app -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails + from ..core.validate_user import ControlAccess from cryptography import x509 from cryptography.hazmat.backends import default_backend diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py index 00cf9b7d902663a8ef93e804fd5379e967af66a2..06e597cd2fe70812198b0cdb15df3ac6827708d4 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py @@ -1,23 +1,18 @@ -import sys + import os -import pymongo + import secrets from flask import current_app, Flask, Response -import json -from ..db.db import MongoDatabse -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails from pymongo import ReturnDocument from ..util import dict_to_camel_case, clean_empty +from ..encoder import JSONEncoder from .resources import Resource -from .responses import bad_request_error, internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response -from ..models.invocation_log import InvocationLog -# from .publisher import Publisher + +from .responses import internal_server_error, not_found_error, unauthorized_error, make_response from .redis_event import RedisEvent -import copy +import json -# publisher_ops = Publisher() class LoggingInvocationOperations(Resource): @@ -85,7 +80,7 @@ class LoggingInvocationOperations(Resource): current_app.logger.debug("Check service apis") event=None - invocation_log_base=json.loads(json.dumps(invocationlog, cls=JSONEncoder)) + invocation_log_base=json.loads(json.dumps(invocationlog.to_dict(), cls=JSONEncoder)) for log in invocationlog.logs: result = self.__check_service_apis(log.api_id, log.api_name) @@ -102,9 +97,9 @@ class LoggingInvocationOperations(Resource): event="SERVICE_API_INVOCATION_FAILURE" current_app.logger.info(event) - invocation_log_base['logs']=[log] + invocation_log_base['logs']=[log.to_dict()] invocationLogs=[invocation_log_base] - RedisEvent(event,"invocationLogs",invocationLogs).send_event() + RedisEvent(event,"invocation_logs",invocationLogs).send_event() current_app.logger.debug("After log check") @@ -127,7 +122,7 @@ class LoggingInvocationOperations(Resource): existing_invocationlog['logs'].append(updated_invocation_log) mycol.find_one_and_update(my_query, {"$set": existing_invocationlog}, projection={'_id': 0, 'log_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) - res = make_response(object=invocationlog, status=201) + res = make_response(object=dict_to_camel_case(clean_empty(invocationlog.to_dict())), status=201) current_app.logger.debug("Invocation Logs response ready") apis_added = {log.api_id:log.api_name for log in invocationlog.logs} diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py index d55b30c74cf87bf22eec115dfc1bd0e6d413a018..d5a3552d6b3459a77d30df65d0bbda4a86c7fa61 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py @@ -1,5 +1,5 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from abc import ABC +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py index 3a136b1459f0cad9410148983fbdfbbe294a03d0..6940f646be2ef7a7b20fa33cc1b3b8e6ca008ffb 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py @@ -1,8 +1,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import dict_to_camel_case, clean_empty import json -from bson import json_util mimetype = "application/json" @@ -16,28 +16,48 @@ def make_response(object, status): def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) def unauthorized_error(detail, cause): prob = ProblemDetails(title="Unauthorized", status=401, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py index 2a8943738218ab542605b4a3e5053ddd7dbefaf9..13d8b6ab7a82a8287308b347454a35dc6d719b26 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py @@ -4,6 +4,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import dict_to_camel_case, clean_empty + class ControlAccess(Resource): @@ -18,6 +20,9 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py index 96a39f3aa05be3e6945173dd832fc4777a4e01dd..f706e5f11a4943337740a7d7cf1ffa2cb1cdf5f6 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py @@ -1,9 +1,8 @@ -import atexit + import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config -from bson.codec_options import CodecOptions +from config import Config import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py index efa1154be1714b16879b8fa9ee6d09169c86076e..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from api_invocation_logs.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py index af555673357bf337cf79d74e3dae42b9c84dafb9..ec1430110f5a167f67a8c083cfda84af63a678d4 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py @@ -1,8 +1,8 @@ import datetime import six -import typing -from api_invocation_logs import typing_utils +import typing_utils + def clean_empty(d): if isinstance(d, dict): @@ -15,6 +15,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/wsgi.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt b/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt index 0dfa8b621257a6601b7645cf6620300ad22be18c..b08bd828f28be3597ba68c0748cbc4ac7ca6c1ce 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt @@ -19,3 +19,5 @@ opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 pyopenssl == 23.0.0 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Publish_Service_API/Dockerfile b/services/TS29222_CAPIF_Publish_Service_API/Dockerfile index b2e6167309094b21ac6526fb45d679861032d65f..c11e2d64a014a7a98ec58a902e9b64d26519f405 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/Dockerfile +++ b/services/TS29222_CAPIF_Publish_Service_API/Dockerfile @@ -12,6 +12,6 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] +ENTRYPOINT ["gunicorn"] -CMD ["-m", "published_apis"] \ No newline at end of file +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/published_apis", "wsgi:app"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/__main__.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/app.py similarity index 94% rename from services/TS29222_CAPIF_Publish_Service_API/published_apis/__main__.py rename to services/TS29222_CAPIF_Publish_Service_API/published_apis/app.py index dfba9ef99bcbb5c96e9260d7d1a1f22ace86e6b1..d8c3fc57d3933da040184fdb26e1ea17b0fe4efa 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/__main__.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/app.py @@ -3,15 +3,14 @@ import connexion import logging -from published_apis import encoder +# from published_apis import encoder +import encoder -from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient -from .config import Config +from config import Config from logging.handlers import RotatingFileHandler -from .core.consumer_messager import Subscriber -from flask_executor import Executor +from core.consumer_messager import Subscriber + import os from fluent import sender from flask_executor import Executor @@ -24,10 +23,9 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - - NAME = "Publish-Service" + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -86,7 +84,6 @@ def configure_monitoring(app, config): l.addHandler(FluentBitHandler()) - def configure_logging(app): del app.logger.handlers[:] loggers = [app.logger, ] @@ -114,6 +111,7 @@ def verbose_formatter(): datefmt='%d/%m/%Y %H:%M:%S' ) + app = connexion.App(__name__, specification_dir='./openapi/') app.app.json_encoder = encoder.JSONEncoder app.add_api('openapi.yaml', @@ -133,10 +131,7 @@ if eval(os.environ.get("MONITORING").lower().capitalize()): executor = Executor(app.app) subscriber = Subscriber() + @app.app.before_first_request def up_listener(): executor.submit(subscriber.listen) - - -if __name__ == '__main__': - app.run(debug=True, port=8080) diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime 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 dd43886f522f8c131e0a3c6e7ae569d8f5fde3f9..62e506a6be747d94efa513917913f03a75f20ca3 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,19 +1,15 @@ import connexion -from published_apis.models.service_api_description import ServiceAPIDescription # noqa: E501 -from ..core import serviceapidescriptions +from ..models.service_api_description import ServiceAPIDescription # noqa: E501 from ..core.serviceapidescriptions import PublishServiceOperations -from ..core.publisher import Publisher from flask import Response, request, current_app -from flask_jwt_extended import jwt_required, get_jwt_identity -from flask import current_app -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails + from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps + service_operations = PublishServiceOperations() valid_user = ControlAccess() diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py index 6e329a486848233a1c0600e5625d095e32a54661..cb2f0b937a55d762a7f02bcdbc09d44a1865a5b9 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py @@ -1,7 +1,5 @@ from flask import current_app -from cryptography import x509 -from cryptography.hazmat.backends import default_backend from .resources import Resource diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py index 6f40a047f5c7d6378a9518a1c492f24bebaddf69..f781ead9e3beb684bf6face38ef9c0e4fd5cc5bc 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py @@ -1,10 +1,5 @@ # subscriber.py import redis -import time -import sys -import json -import asyncio -from threading import Thread from .internal_service_ops import InternalServiceOps from flask import current_app diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py index f7b0c3c4b25f9abbe24d2dc734a72a93ffe0af01..34fcdf453873b4b59a894d9f6b96b7ce1a217c2e 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py @@ -1,5 +1,4 @@ import redis -import sys class Publisher(): 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 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 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,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py index c1809eda5a7669e869fb2e83fa7ebf2628f4d3f2..c61eae0c65bf15bf261139128c75a495799a927f 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py @@ -1,37 +1,63 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import dict_to_camel_case, clean_empty import json -from bson import json_util + mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) def unauthorized_error(detail, cause): prob = ProblemDetails(title="Unauthorized", status=401, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype=mimetype) \ No newline at end of file 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 85b9b781bdb61168b69c461a6ed7cafaa94ac490..41ce03de2243a40442ec3cddd04b11eebf5018bf 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 @@ -1,21 +1,11 @@ -import sys - -import pymongo from pymongo import ReturnDocument import secrets from flask import current_app, Flask, Response -import json -from pymongo import response -from ..db.db import MongoDatabse -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails from .resources import Resource -from published_apis.models.service_api_description import ServiceAPIDescription from datetime import datetime from ..util import dict_to_camel_case, clean_empty -from .responses import bad_request_error, internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response -from bson import json_util +from .responses import internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response from .auth_manager import AuthManager from .redis_event import RedisEvent from .publisher import Publisher @@ -119,9 +109,10 @@ class PublishServiceOperations(Resource): self.auth_manager.add_auth_service(api_id, apf_id) current_app.logger.debug("Service inserted in database") - res = make_response(object=serviceapidescription, status=201) + + res = make_response(object=dict_to_camel_case(clean_empty(serviceapidescription.to_dict())), status=201) res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + \ - str(apf_id) + "/service-apis/" + str(api_id) + str(apf_id) + "/service-apis/" + str(api_id) if res.status_code == 201: current_app.logger.info("Service published") diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py index 67d434dc13624075dbc1698d90046d9c10326ac8..5eed2c946e1e8388518061b10a862143f6c1b82d 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py @@ -4,6 +4,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import dict_to_camel_case, clean_empty class ControlAccess(Resource): @@ -18,6 +19,9 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature or "services" not in cert_entry["resources"] or service_id not in cert_entry["resources"]["services"]: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: 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 91f7b6bb9408859d41a1e9a8c05be563669902fd..e30cb6667667f6cf055b1ea88bec89de6044e4a2 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 @@ -1,8 +1,7 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py index c753f45e1f69eda91e19d4328d2447f9e7114fe0..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from published_apis.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py index 3f53de6f85ebf9316a86066e36089d73a96bd886..c43b2746c4085a6f6de5a3555a19f3848aa0ad40 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py @@ -1,8 +1,7 @@ import datetime import six -import typing -from published_apis import typing_utils +import typing_utils def clean_empty(d): diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/wsgi.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Publish_Service_API/requirements.txt b/services/TS29222_CAPIF_Publish_Service_API/requirements.txt index 0ba8fb534606696f9f5e2cd5164563a048709b67..cd12aa41e801e40c417bf01b4d04edb1e6677d0c 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/requirements.txt +++ b/services/TS29222_CAPIF_Publish_Service_API/requirements.txt @@ -19,3 +19,5 @@ flask_executor == 1.0.0 pyopenssl == 23.0.0 redis == 4.5.4 flask_executor == 1.0.0 +gunicorn==22.0.0 +packaging==24.0 diff --git a/services/TS29222_CAPIF_Routing_Info_API/Dockerfile b/services/TS29222_CAPIF_Routing_Info_API/Dockerfile index 9911d06b662dc1890945b8ec73c862a5ae5a2fab..cfa4b5dfe4888a1efa8fb9551f707f21c93dd73c 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/Dockerfile +++ b/services/TS29222_CAPIF_Routing_Info_API/Dockerfile @@ -11,6 +11,6 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] +ENTRYPOINT ["gunicorn"] -CMD ["-m", "capif_routing_info"] \ No newline at end of file +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/capif_routing_info", "wsgi:app"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__main__.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__main__.py deleted file mode 100644 index e595fa02106ed80d620b8eb00f1d2a421bb1ee5f..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__main__.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python3 - -import connexion - -from capif_routing_info import encoder - - -def main(): - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'CAPIF_Routing_Info_API'}, - pythonic_params=True) - - app.run(port=8080) - - -if __name__ == '__main__': - main() diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/app.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/app.py new file mode 100644 index 0000000000000000000000000000000000000000..89135805b065ac22200eecdbf76b699f7035e680 --- /dev/null +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/app.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import connexion +import encoder + + +app = connexion.App(__name__, specification_dir='./openapi/') +app.app.json_encoder = encoder.JSONEncoder +app.add_api('openapi.yaml', + arguments={'title': 'CAPIF_Routing_Info_API'}, + pythonic_params=True) diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py index 7cd07dd74ff2634a9487083283cad4ef354c61ae..13c24a3a52464679a765141f1963cc5bb21248ec 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py @@ -1,9 +1,4 @@ -import connexion -import six - -from capif_routing_info.models.problem_details import ProblemDetails # noqa: E501 -from capif_routing_info.models.routing_info import RoutingInfo # noqa: E501 -from capif_routing_info import util +from ..models.routing_info import RoutingInfo # noqa: E501 def service_apis_service_api_id_get(service_api_id, aef_id, supp_feat=None): # noqa: E501 diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py index b53647004a14457d83693f5909b69425d927d3c8..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from capif_routing_info.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py index 227076550fea5acb4f1f167a777f366215563261..910388bab6fa518b467b13476102000d2b0a0321 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py @@ -2,7 +2,7 @@ import datetime import six import typing -from capif_routing_info import typing_utils +import typing_utils def _deserialize(data, klass): diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/wsgi.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Routing_Info_API/requirements.txt b/services/TS29222_CAPIF_Routing_Info_API/requirements.txt index 1be0346f149043abdcafbd540c98c73eca75275e..e4be1ef6b91acd656f04127c542692abdb9b7b6b 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/requirements.txt +++ b/services/TS29222_CAPIF_Routing_Info_API/requirements.txt @@ -3,3 +3,5 @@ swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 setuptools >= 21.0.0 Flask == 2.0.3 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Security_API/capif_security/__main__.py b/services/TS29222_CAPIF_Security_API/capif_security/__main__.py deleted file mode 100644 index 98d396499dd9e5b056d1d63d9fbaa3dcf8fae442..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Security_API/capif_security/__main__.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python3 - -import connexion -import logging -from capif_security import encoder -from flask_jwt_extended import JWTManager -from .config import Config -from .core.consumer_messager import Subscriber -from threading import Thread -from flask_executor import Executor -from logging.handlers import RotatingFileHandler -import sys -import os -from fluent import sender -from flask_executor import Executor -from opentelemetry.instrumentation.flask import FlaskInstrumentor -from opentelemetry import trace -from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter -from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator -from opentelemetry.sdk.resources import Resource -from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export import BatchSpanProcessor -from opentelemetry.instrumentation.redis import RedisInstrumentor - - - -NAME = "Security-Service" - -def configure_monitoring(app, config): - - resource = Resource(attributes={"service.name": NAME}) - - fluent_bit_host = config['monitoring']['fluent_bit_host'] - fluent_bit_port = config['monitoring']['fluent_bit_port'] - fluent_bit_sender = sender.FluentSender('Security-Service', host=fluent_bit_host, port=fluent_bit_port) - propagator = TraceContextTextMapPropagator() - - tracer_provider = TracerProvider(resource=resource) - trace.set_tracer_provider(tracer_provider) - exporter = OTLPSpanExporter(endpoint=f"http://{config['monitoring']['opentelemetry_url']}:{config['monitoring']['opentelemetry_port']}", insecure=True) - span_processor = BatchSpanProcessor( - exporter, - max_queue_size=config['monitoring']['opentelemetry_max_queue_size'], - schedule_delay_millis=config['monitoring']['opentelemetry_schedule_delay_millis'], - max_export_batch_size=config['monitoring']['opentelemetry_max_export_batch_size'], - export_timeout_millis=config['monitoring']['opentelemetry_export_timeout_millis'], - ) - - trace.get_tracer_provider().add_span_processor(span_processor) - - FlaskInstrumentor().instrument_app(app) - - RedisInstrumentor().instrument() - - class FluentBitHandler(logging.Handler): - - def __init__(self): - logging.Handler.__init__(self) - - def emit(self, record): - log_entry = self.format(record) - log_data = { - 'message': log_entry, - 'level': record.levelname, - 'timestamp': record.created, - 'logger': record.name, - 'function': record.funcName, - 'line': record.lineno, - 'container_name': os.environ.get('CONTAINER_NAME', ''), - } - - # # Obtener el trace ID actual - current_context = trace.get_current_span().get_span_context() - - trace_id = current_context.trace_id - traceparent_id = current_context.span_id - log_data['traceID'] = hex(trace_id)[2:] - if traceparent_id != None: - log_data['traceparent'] = hex(traceparent_id)[2:] - fluent_bit_sender.emit('Security-Service', log_data) - - loggers = [app.logger, ] - for l in loggers: - l.addHandler(FluentBitHandler()) - - -def configure_logging(app): - del app.logger.handlers[:] - loggers = [app.logger, ] - handlers = [] - console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) - console_handler.setFormatter(verbose_formatter()) - file_handler = RotatingFileHandler(filename="security_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) - file_handler.setFormatter(verbose_formatter()) - handlers.append(console_handler) - handlers.append(file_handler) - - for l in loggers: - for handler in handlers: - l.addHandler(handler) - l.propagate = False - l.setLevel(logging.DEBUG) - - -def verbose_formatter(): - return logging.Formatter( - '{"timestamp": "%(asctime)s", "level": "%(levelname)s", "logger": "%(name)s", "function": "%(funcName)s", "line": %(lineno)d, "message": %(message)s}', - datefmt='%d/%m/%Y %H:%M:%S' - ) - -def main(): - - with open("/usr/src/app/capif_security/server.key", "rb") as key_file: - key_data = key_file.read() - - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - - - app.app.config['JWT_ALGORITHM'] = 'RS256' - app.app.config['JWT_PRIVATE_KEY'] = key_data - app.add_api('openapi.yaml', - arguments={'title': 'CAPIF_Security_API'}, - pythonic_params=True) - - JWTManager(app.app) - subscriber = Subscriber() - - config = Config() - configure_logging(app.app) - - if eval(os.environ.get("MONITORING").lower().capitalize()): - configure_monitoring(app.app, config.get_config()) - - executor = Executor(app.app) - - @app.app.before_first_request - def up_listener(): - executor.submit(subscriber.listen) - - - app.run(port=8080, debug=True) - -if __name__ == '__main__': - main() - diff --git a/services/TS29222_CAPIF_Security_API/capif_security/app.py b/services/TS29222_CAPIF_Security_API/capif_security/app.py new file mode 100644 index 0000000000000000000000000000000000000000..975488eeff6a4d89c2b71328d17a0b3ff15c912b --- /dev/null +++ b/services/TS29222_CAPIF_Security_API/capif_security/app.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 + +import connexion +import logging +import encoder +from flask_jwt_extended import JWTManager +from config import Config +from core.consumer_messager import Subscriber +from logging.handlers import RotatingFileHandler +import os +from fluent import sender +from flask_executor import Executor +from opentelemetry.instrumentation.flask import FlaskInstrumentor +from opentelemetry import trace +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter +from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator +from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor +from opentelemetry.instrumentation.redis import RedisInstrumentor + +NAME = "Security-Service" + + +def configure_monitoring(app, config): + + resource = Resource(attributes={"service.name": NAME}) + + fluent_bit_host = config['monitoring']['fluent_bit_host'] + fluent_bit_port = config['monitoring']['fluent_bit_port'] + fluent_bit_sender = sender.FluentSender('Security-Service', host=fluent_bit_host, port=fluent_bit_port) + propagator = TraceContextTextMapPropagator() + + tracer_provider = TracerProvider(resource=resource) + trace.set_tracer_provider(tracer_provider) + exporter = OTLPSpanExporter(endpoint=f"http://{config['monitoring']['opentelemetry_url']}:{config['monitoring']['opentelemetry_port']}", insecure=True) + span_processor = BatchSpanProcessor( + exporter, + max_queue_size=config['monitoring']['opentelemetry_max_queue_size'], + schedule_delay_millis=config['monitoring']['opentelemetry_schedule_delay_millis'], + max_export_batch_size=config['monitoring']['opentelemetry_max_export_batch_size'], + export_timeout_millis=config['monitoring']['opentelemetry_export_timeout_millis'], + ) + + trace.get_tracer_provider().add_span_processor(span_processor) + + FlaskInstrumentor().instrument_app(app) + + RedisInstrumentor().instrument() + + class FluentBitHandler(logging.Handler): + + def __init__(self): + logging.Handler.__init__(self) + + def emit(self, record): + log_entry = self.format(record) + log_data = { + 'message': log_entry, + 'level': record.levelname, + 'timestamp': record.created, + 'logger': record.name, + 'function': record.funcName, + 'line': record.lineno, + 'container_name': os.environ.get('CONTAINER_NAME', ''), + } + + # # Obtener el trace ID actual + current_context = trace.get_current_span().get_span_context() + + trace_id = current_context.trace_id + traceparent_id = current_context.span_id + log_data['traceID'] = hex(trace_id)[2:] + if traceparent_id != None: + log_data['traceparent'] = hex(traceparent_id)[2:] + fluent_bit_sender.emit('Security-Service', log_data) + + loggers = [app.logger, ] + for l in loggers: + l.addHandler(FluentBitHandler()) + + +def configure_logging(app): + del app.logger.handlers[:] + loggers = [app.logger, ] + handlers = [] + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.DEBUG) + console_handler.setFormatter(verbose_formatter()) + file_handler = RotatingFileHandler(filename="security_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) + file_handler.setLevel(logging.DEBUG) + file_handler.setFormatter(verbose_formatter()) + handlers.append(console_handler) + handlers.append(file_handler) + + for l in loggers: + for handler in handlers: + l.addHandler(handler) + l.propagate = False + l.setLevel(logging.DEBUG) + + +def verbose_formatter(): + return logging.Formatter( + '{"timestamp": "%(asctime)s", "level": "%(levelname)s", "logger": "%(name)s", "function": "%(funcName)s", "line": %(lineno)d, "message": %(message)s}', + datefmt='%d/%m/%Y %H:%M:%S' + ) + + +with open("/usr/src/app/capif_security/server.key", "rb") as key_file: + key_data = key_file.read() + +app = connexion.App(__name__, specification_dir='./openapi/') +app.app.json_encoder = encoder.JSONEncoder + + +app.app.config['JWT_ALGORITHM'] = 'RS256' +app.app.config['JWT_PRIVATE_KEY'] = key_data +app.add_api('openapi.yaml', + arguments={'title': 'CAPIF_Security_API'}, + pythonic_params=True) + +JWTManager(app.app) +subscriber = Subscriber() + +config = Config() +configure_logging(app.app) + +if eval(os.environ.get("MONITORING").lower().capitalize()): + configure_monitoring(app.app, config.get_config()) + +executor = Executor(app.app) + +@app.app.before_first_request +def up_listener(): + executor.submit(subscriber.listen) diff --git a/services/TS29222_CAPIF_Security_API/capif_security/config.py b/services/TS29222_CAPIF_Security_API/capif_security/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/config.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py b/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py index e37ecde5a07a1f6bd10de046189543967ea02e74..7e04d4df353bd4227d5b7bda72e3cb7236cf1dab 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py @@ -1,26 +1,20 @@ import connexion -import six - -from capif_security.models.access_token_err import AccessTokenErr # noqa: E501 -from capif_security.models.access_token_rsp import AccessTokenRsp # noqa: E501 -from capif_security.models.access_token_req import AccessTokenReq # noqa: E501 -from capif_security.models.security_notification import SecurityNotification # noqa: E501 -from capif_security.models.service_security import ServiceSecurity # noqa: E501 -from capif_security import util + +from ..models.access_token_req import AccessTokenReq # noqa: E501 +from ..models.security_notification import SecurityNotification # noqa: E501 +from ..models.service_security import ServiceSecurity # noqa: E501 + from ..core.servicesecurity import SecurityOperations -from ..core.consumer_messager import Subscriber + from ..core.publisher import Publisher -import json + from flask import Response, request, current_app -from flask_jwt_extended import jwt_required, get_jwt_identity -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails -import sys + from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps -import pymongo + service_security_ops = SecurityOperations() publish_ops = Publisher() diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py b/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py index 8bb8574b6b109361008aff091078519e7a021e21..43445583236a5743ea1475079a3c329bb0788787 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py @@ -1,10 +1,5 @@ # subscriber.py import redis -import time -import sys -import json -import asyncio -from threading import Thread from .internal_security_ops import InternalSecurityOps from flask import current_app diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py b/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py index d5cbd968beee2cae29b63b8ad679f0e6d776da1f..d1b28d5938fa8f7c1d2c5d2bf9d4a3a9b3c68fda 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py @@ -1,5 +1,4 @@ -from flask import current_app from .resources import Resource class InternalSecurityOps(Resource): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py b/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py index 5d69adc7b79d47ce637309e3046f3937856e58cc..2efad5f7f28459e561ddcf9d22612275e1435dea 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py @@ -1,7 +1,5 @@ import requests -from ..encoder import JSONEncoder -import sys -import json + class Notifications(): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py b/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py index f7b0c3c4b25f9abbe24d2dc734a72a93ffe0af01..8292de4d4330b14c17be74e7448403b56fc5b9e3 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py @@ -1,5 +1,5 @@ import redis -import sys + class Publisher(): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py b/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py index 2ba2a0f944c9ff47009a2d461aafde25751fcd88..53a35e5d60f0fbe6fd7735e0c766bee233f84b47 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py @@ -1,7 +1,8 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from abc import ABC +from db.db import MongoDatabse from .notification import Notifications + class Resource(ABC): def __init__(self): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py b/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py index 26e82b68c92cc01fbd9682f119d5d6e3d58711a8..9c2020c79bb6e0cc6e68a084607a61d563c48657 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py @@ -2,36 +2,62 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response import json -from bson import json_util +from ..util import dict_to_camel_case, clean_empty mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) + def unauthorized_error(detail, cause): prob = ProblemDetails(title="Unauthorized", status=401, detail=detail, cause=cause) + prob = prob.to_dict() + prob = clean_empty(prob) + prob = dict_to_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py b/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py index 8f48465eddcb2254f53b46545aaa9517ac3450f3..9fe7838a47479a17b0233dd7698c3bb08958c670 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py @@ -1,31 +1,22 @@ -import sys -import pymongo from pymongo import ReturnDocument -import secrets -import re + import rfc3987 from flask import current_app, Flask, Response from flask_jwt_extended import create_access_token from datetime import datetime, timedelta import json -from ..db.db import MongoDatabse -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails -from ..models.access_token_rsp import AccessTokenRsp -from ..models.access_token_claims import AccessTokenClaims from bson import json_util -import requests from ..core.publisher import Publisher from ..models.access_token_err import AccessTokenErr -from ..models.service_security import ServiceSecurity +from ..models.access_token_rsp import AccessTokenRsp +from ..models.access_token_claims import AccessTokenClaims from ..util import dict_to_camel_case, clean_empty from .responses import not_found_error, make_response, bad_request_error, internal_server_error, forbidden_error -from .notification import Notifications from .resources import Resource -import os from .redis_event import RedisEvent +import os publish_ops = Publisher() @@ -55,9 +46,8 @@ class SecurityOperations(Resource): header = scope[0:4] if header != "3gpp": current_app.logger.error("Bad format scope") - token_error = AccessTokenErr( - error="invalid_scope", error_description="The first characters must be '3gpp'") - return make_response(object=token_error, status=400) + token_error = AccessTokenErr(error="invalid_scope", error_description="The first characters must be '3gpp'") + return make_response(object=clean_empty(token_error.to_dict()), status=400) _, body = scope.split("#") @@ -70,29 +60,27 @@ class SecurityOperations(Resource): for group in groups: aef_id, api_names = group.split(":") if aef_id not in aef_security_context: - current_app.logger.error( - "Bad format Scope, not valid aef id ") - token_error = AccessTokenErr( - error="invalid_scope", error_description="One of aef_id not belongs of your security context") - return make_response(object=token_error, status=400) + current_app.logger.error("Bad format Scope, not valid aef id ") + token_error = AccessTokenErr(error="invalid_scope", error_description="One of aef_id not belongs of your security context") + return make_response(object=clean_empty(token_error.to_dict()), status=400) + api_names = api_names.split(",") for api_name in api_names: service = capif_service_col.find_one( {"$and": [{"api_name": api_name}, {self.filter_aef_id: aef_id}]}) if service is None: - current_app.logger.error( - "Bad format Scope, not valid api name") + current_app.logger.error("Bad format Scope, not valid api name") token_error = AccessTokenErr( - error="invalid_scope", error_description="One of the api names does not exist or is not associated with the aef id provided") - return make_response(object=token_error, status=400) + error="invalid_scope", + error_description="One of the api names does not exist or is not associated with the aef id provided") + return make_response(object=clean_empty(token_error.to_dict()), status=400) return None except Exception as e: current_app.logger.error("Bad format Scope: " + e) - token_error = AccessTokenErr( - error="invalid_scope", error_description="malformed scope") - return make_response(object=token_error, status=400) + token_error = AccessTokenErr(error="invalid_scope", error_description="malformed scope") + return make_response(object=clean_empty(token_error.to_dict()), status=400) def __init__(self): Resource.__init__(self) @@ -208,9 +196,10 @@ class SecurityOperations(Resource): rec.update(service_security.to_dict()) mycol.insert_one(rec) - res = make_response(object=service_security, status=201) + res = make_response(object=dict_to_camel_case(clean_empty(service_security.to_dict())), status=201) res.headers['Location'] = "https://{}/capif-security/v1/trustedInvokers/{}".format( os.getenv('CAPIF_HOSTNAME'), str(api_invoker_id)) + return res except Exception as e: @@ -274,20 +263,20 @@ class SecurityOperations(Resource): invoker = invokers_col.find_one( {"api_invoker_id": access_token_req["client_id"]}) if invoker is None: - client_id_error = AccessTokenErr( - error="invalid_client", error_description="Client Id not found") - return make_response(object=client_id_error, status=400) + client_id_error = AccessTokenErr(error="invalid_client", error_description="Client Id not found") + return make_response(object=clean_empty(client_id_error.to_dict()), status=400) + if access_token_req["grant_type"] != "client_credentials": - client_id_error = AccessTokenErr(error="unsupported_grant_type", error_description="Invalid value for `grant_type` ({0}), must be one of ['client_credentials'] - 'grant_type'" + client_id_error = AccessTokenErr(error="unsupported_grant_type", + error_description="Invalid value for `grant_type` ({0}), must be one of ['client_credentials'] - 'grant_type'" .format(access_token_req["grant_type"])) - return make_response(object=client_id_error, status=400) + return make_response(object=clean_empty(client_id_error.to_dict()), status=400) service_security = mycol.find_one({"api_invoker_id": security_id}) if service_security is None: - current_app.logger.error( - "Not found security context with id: " + security_id) - return not_found_error(detail=security_context_not_found_detail, cause=api_invoker_no_context_cause) + current_app.logger.error("Not found security context with id: " + security_id) + return not_found_error(detail= security_context_not_found_detail, cause=api_invoker_no_context_cause) result = self.__check_scope( access_token_req["scope"], service_security) @@ -307,7 +296,8 @@ class SecurityOperations(Resource): current_app.logger.debug("Created access token") - res = make_response(object=access_token_resp, status=200) + # res = make_response(object=dict_to_camel_case(clean_empty(access_token_resp.to_dict())), status=200) + res = make_response(object=clean_empty(access_token_resp.to_dict()), status=200) return res except Exception as e: exception = "An exception occurred in return token" @@ -363,11 +353,11 @@ class SecurityOperations(Resource): result = mycol.find_one_and_update(old_object, {"$set": service_security}, projection={ '_id': 0, "api_invoker_id": 0}, return_document=ReturnDocument.AFTER, upsert=False) - result = clean_empty(result) + # result = clean_empty(result) current_app.logger.debug("Updated security context") - res = make_response(object=dict_to_camel_case(result), status=200) + res= make_response(object=dict_to_camel_case(clean_empty(result)), status=200) res.headers['Location'] = "https://${CAPIF_HOSTNAME}/capif-security/v1/trustedInvokers/" + str( api_invoker_id) return res diff --git a/services/TS29222_CAPIF_Security_API/capif_security/db/db.py b/services/TS29222_CAPIF_Security_API/capif_security/db/db.py index dbbb99e7899c2bb68867f1c3f99b869e578c1efa..4a009dbf6a4712da2fac7020841a2e7e4ec10962 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/db/db.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/db/db.py @@ -2,7 +2,7 @@ import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor diff --git a/services/TS29222_CAPIF_Security_API/capif_security/encoder.py b/services/TS29222_CAPIF_Security_API/capif_security/encoder.py index 9d6964e4ccb171ae9174d22c6d790d186f42cebf..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/encoder.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from capif_security.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/util.py b/services/TS29222_CAPIF_Security_API/capif_security/util.py index 873c290d1d0bd4a1b6e0a9ff18e60630cc836f14..00ceb152b3c95233fec243ca5e3b8304c4b3611c 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/util.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/util.py @@ -1,8 +1,7 @@ import datetime import six -import typing -from capif_security import typing_utils +import typing_utils def clean_empty(d): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/wsgi.py b/services/TS29222_CAPIF_Security_API/capif_security/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Security_API/capif_security/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Security_API/requirements.txt b/services/TS29222_CAPIF_Security_API/requirements.txt index 220adafdb62aa6e9343fde8c22dc7b2f9c7e0ba7..835b8ca6c9732a845de5129511f58e62f4e7b4a5 100644 --- a/services/TS29222_CAPIF_Security_API/requirements.txt +++ b/services/TS29222_CAPIF_Security_API/requirements.txt @@ -19,4 +19,6 @@ fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 -flask_executor == 1.0.0 \ No newline at end of file +flask_executor == 1.0.0 +gunicorn==22.0.0 +packaging==24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Security_API/security_prepare.sh b/services/TS29222_CAPIF_Security_API/security_prepare.sh index c28b38929ae793399b64b70fab1ccbcccc6aeab0..94bece0582e614c49d6fbab23307984a2ad9875d 100644 --- a/services/TS29222_CAPIF_Security_API/security_prepare.sh +++ b/services/TS29222_CAPIF_Security_API/security_prepare.sh @@ -15,5 +15,5 @@ curl -k -retry 30 \ --request GET "$VAULT_ADDR/v1/secret/data/server_cert/private" 2>/dev/null | jq -r '.data.data.key' -j > /usr/src/app/capif_security/server.key -cd /usr/src/app/ -python3 -m capif_security \ No newline at end of file +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/capif_security wsgi:app \ No newline at end of file diff --git a/services/helper/Dockerfile b/services/helper/Dockerfile index 2bc3b3390f4d6d7f5879af105f65308e7a5d8263..2c521b77a2f232b87dd82c95f7f8fba652d083a7 100644 --- a/services/helper/Dockerfile +++ b/services/helper/Dockerfile @@ -13,4 +13,6 @@ COPY . /usr/src/app EXPOSE 8080 -CMD ["python3", "-m", "helper_service"] +ENTRYPOINT ["gunicorn"] + +CMD ["--bind", "0.0.0.0:8080", "--chdir", "/usr/src/app/helper_service", "wsgi:app"] diff --git a/services/helper/helper_service/__main__.py b/services/helper/helper_service/app.py similarity index 83% rename from services/helper/helper_service/__main__.py rename to services/helper/helper_service/app.py index 69411aafd2bde2eef90de3c33047ac594dbdc035..bdc0007da01ff45d6b886fb2fd9eeee52bc983e6 100644 --- a/services/helper/helper_service/__main__.py +++ b/services/helper/helper_service/app.py @@ -1,8 +1,8 @@ from flask import Flask import logging -from .controllers.helper_controller import helper_routes +from controllers.helper_controller import helper_routes from OpenSSL.crypto import PKey, TYPE_RSA, X509Req, dump_certificate_request, FILETYPE_PEM, dump_privatekey -from .config import Config +from config import Config import json import requests @@ -26,7 +26,7 @@ csr_request = dump_certificate_request(FILETYPE_PEM, req) private_key = dump_privatekey(FILETYPE_PEM, key) # Save superadmin private key -key_file = open("helper_service/certs/superadmin.key", 'wb+') +key_file = open("certs/superadmin.key", 'wb+') key_file.write(bytes(private_key)) key_file.close() @@ -44,7 +44,7 @@ response = requests.request("POST", url, headers=headers, data=data, verify = Fa superadmin_cert = json.loads(response.text)['data']['certificate'] # Save the superadmin certificate -cert_file = open("helper_service/certs/superadmin.crt", 'wb') +cert_file = open("certs/superadmin.crt", 'wb') cert_file.write(bytes(superadmin_cert, 'utf-8')) cert_file.close() @@ -56,12 +56,10 @@ headers = { response = requests.request("GET", url, headers=headers, verify = False) ca_root = json.loads(response.text)['data']['data']['ca'] -cert_file = open("helper_service/certs/ca_root.crt", 'wb') +cert_file = open("certs/ca_root.crt", 'wb') cert_file.write(bytes(ca_root, 'utf-8')) cert_file.close() app.register_blueprint(helper_routes) app.logger.setLevel(logging.DEBUG) -if __name__ == '__main__': - app.run(host='0.0.0.0', port=8080, debug=True) \ No newline at end of file diff --git a/services/helper/helper_service/config.py b/services/helper/helper_service/config.py index 444a23201168fceb276fa44b81f2417d8fc2afa6..f9574a678498483f4e138d4890fc1fa079cebce4 100644 --- a/services/helper/helper_service/config.py +++ b/services/helper/helper_service/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/helper/helper_service/controllers/helper_controller.py b/services/helper/helper_service/controllers/helper_controller.py index 995d33590d5b6b32cb14961ed60e1d35463109a9..f645a564ca88eb238ced5784cdc5ff2450910075 100644 --- a/services/helper/helper_service/controllers/helper_controller.py +++ b/services/helper/helper_service/controllers/helper_controller.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 from flask import Blueprint, request, current_app, jsonify -from ..core.helper_operations import HelperOperations -from ..config import Config +from core.helper_operations import HelperOperations +from config import Config config = Config().get_config() diff --git a/services/helper/helper_service/core/helper_operations.py b/services/helper/helper_service/core/helper_operations.py index aed9da5ab74357632681679f0b99883b9f4746a7..9e6354675ae348efbd5b9f47c940f6145f371103 100644 --- a/services/helper/helper_service/core/helper_operations.py +++ b/services/helper/helper_service/core/helper_operations.py @@ -1,7 +1,7 @@ from flask import jsonify, current_app import pymongo -from ..db.db import MongoDatabse -from ..config import Config +from db.db import MongoDatabse +from config import Config import requests import os diff --git a/services/helper/helper_service/db/db.py b/services/helper/helper_service/db/db.py index 9820a92705e4c73151ffa216bab58b7d0cb866c0..bb2853ef6638b8d2294edbd8d7d1c2c225c8a061 100644 --- a/services/helper/helper_service/db/db.py +++ b/services/helper/helper_service/db/db.py @@ -1,7 +1,7 @@ import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions class MongoDatabse(): diff --git a/services/helper/helper_service/wsgi.py b/services/helper/helper_service/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/helper/helper_service/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/helper/requirements.txt b/services/helper/requirements.txt index 68d82b28cd3fcc11703f52df02a7340086b90d33..0e444da92643ea1dacd4f451aef1ccd8c1a7beb4 100644 --- a/services/helper/requirements.txt +++ b/services/helper/requirements.txt @@ -6,3 +6,5 @@ flask_jwt_extended == 4.6.0 pyopenssl == 24.1.0 pyyaml == 6.0.1 requests == 2.32.2 +gunicorn==22.0.0 +packaging==24.0 diff --git a/services/register/register_prepare.sh b/services/register/register_prepare.sh index 4a49b87d7039f7dba68b3f1cce00e77aaa3656c8..2ae8deff25fce905a937fa87767796a9685f8482 100644 --- a/services/register/register_prepare.sh +++ b/services/register/register_prepare.sh @@ -40,5 +40,7 @@ __EOF__ openssl x509 -req -in /usr/src/app/register_service/certs/register.csr -CA /usr/src/app/register_service/certs/registerCA.crt -CAkey /usr/src/app/register_service/certs/registerCA.key -CAcreateserial -out /usr/src/app/register_service/certs/register_cert.crt -days 365 -sha256 -cd /usr/src/app/ -python3 -m register_service \ No newline at end of file +gunicorn --certfile=/usr/src/app/register_service/certs/register_cert.crt \ + --keyfile=/usr/src/app/register_service/certs/register_key.key \ + --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/register_service wsgi:app \ No newline at end of file diff --git a/services/register/register_service/__main__.py b/services/register/register_service/app.py similarity index 80% rename from services/register/register_service/__main__.py rename to services/register/register_service/app.py index aeab95586376f451daaba817261b735fc80b720e..77c3b38121894d3ddc872984e01427eb7ff78642 100644 --- a/services/register/register_service/__main__.py +++ b/services/register/register_service/app.py @@ -1,11 +1,13 @@ + from flask import Flask -from .controllers.register_controller import register_routes +from controllers.register_controller import register_routes from flask_jwt_extended import JWTManager from OpenSSL.crypto import PKey, TYPE_RSA, X509Req, dump_certificate_request, FILETYPE_PEM, dump_privatekey import requests import json -from .config import Config -from .db.db import MongoDatabse +from config import Config +from db.db import MongoDatabse + app = Flask(__name__) @@ -31,7 +33,7 @@ csr_request = dump_certificate_request(FILETYPE_PEM, req) private_key = dump_privatekey(FILETYPE_PEM, key) # Save superadmin private key -key_file = open("register_service/certs/superadmin.key", 'wb+') +key_file = open("certs/superadmin.key", 'wb+') key_file.write(bytes(private_key)) key_file.close() @@ -49,7 +51,7 @@ response = requests.request("POST", url, headers=headers, data=data, verify = Fa superadmin_cert = json.loads(response.text)['data']['certificate'] # Save the superadmin certificate -cert_file = open("register_service/certs/superadmin.crt", 'wb') +cert_file = open("certs/superadmin.crt", 'wb') cert_file.write(bytes(superadmin_cert, 'utf-8')) cert_file.close() @@ -61,7 +63,7 @@ headers = { response = requests.request("GET", url, headers=headers, verify = False) ca_root = json.loads(response.text)['data']['data']['ca'] -cert_file = open("register_service/certs/ca_root.crt", 'wb') +cert_file = open("certs/ca_root.crt", 'wb') cert_file.write(bytes(ca_root, 'utf-8')) cert_file.close() @@ -82,11 +84,4 @@ app.config['JWT_ALGORITHM'] = 'RS256' app.config['JWT_PRIVATE_KEY'] = key_data app.config['REGISTRE_SECRET_KEY'] = config["register"]["register_uuid"] -app.register_blueprint(register_routes) - -#---------------------------------------- -# launch -#---------------------------------------- - -if __name__ == "__main__": - app.run(debug=True, host = '0.0.0.0', port=8080, ssl_context= ("/usr/src/app/register_service/certs/register_cert.crt", "/usr/src/app/register_service/certs/register_key.key")) +app.register_blueprint(register_routes) \ No newline at end of file diff --git a/services/register/register_service/config.py b/services/register/register_service/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/register/register_service/config.py +++ b/services/register/register_service/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/register/register_service/controllers/register_controller.py b/services/register/register_service/controllers/register_controller.py index ded8e8bc9a5fcfb6fa2cfa8bc1f1f033d585b19c..da354690d65706959068276a7e6b81f0cffc3a9d 100644 --- a/services/register/register_service/controllers/register_controller.py +++ b/services/register/register_service/controllers/register_controller.py @@ -1,11 +1,13 @@ #!/usr/bin/env python3 from flask import current_app, Flask, jsonify, request, Blueprint -from ..core.register_operations import RegisterOperations -from ..config import Config + +from core.register_operations import RegisterOperations +from config import Config + from functools import wraps from datetime import datetime, timedelta -from ..db.db import MongoDatabse +from db.db import MongoDatabse from flask_httpauth import HTTPBasicAuth import jwt diff --git a/services/register/register_service/core/register_operations.py b/services/register/register_service/core/register_operations.py index 5082d5152c4c983366d667865bd21e9b85aa593c..dac2654c93111669856f3907b81d09b1a05ab2f1 100644 --- a/services/register/register_service/core/register_operations.py +++ b/services/register/register_service/core/register_operations.py @@ -1,11 +1,12 @@ from flask import Flask, jsonify, request, Response, current_app from flask_jwt_extended import create_access_token -from ..db.db import MongoDatabse +from db.db import MongoDatabse from datetime import datetime -from ..config import Config +from config import Config import requests import uuid + class RegisterOperations: def __init__(self): @@ -38,11 +39,11 @@ class RegisterOperations: exist_user = mycol.find_one({"username": username}) if exist_user is None: - return jsonify("Not exister user with this credentials"), 400 + return jsonify("Not existing user with this credentials"), 400 access_token = create_access_token(identity=(username + " " + exist_user["uuid"])) - cert_file = open("register_service/certs/ca_root.crt", 'rb') + cert_file = open("certs/ca_root.crt", 'rb') ca_root = cert_file.read() cert_file.close() @@ -62,9 +63,9 @@ class RegisterOperations: mycol = self.db.get_col_by_name(self.db.capif_users) try: - - url = f"https://{self.config["ccf"]["url"]}{self.config["ccf"]["helper_remove_user"]}{uuid}" - requests.delete(url, cert=("register_service/certs/superadmin.crt", "register_service/certs/superadmin.key"), verify="register_service/certs/ca_root.crt") + + url = f"https://{self.config["ccf"]["url"]}{self.config["ccf"]["helper_remove_user"]}{uuid}" + requests.delete(url, cert=("certs/superadmin.crt", "certs/superadmin.key"), verify="certs/ca_root.crt") mycol.delete_one({"uuid": uuid}) diff --git a/services/register/register_service/db/db.py b/services/register/register_service/db/db.py index 65a8a83fe4da25f7b992898a60485ccbaa9228d4..fdf448e5be3b675d585bccf141b8e2a6ffe67754 100644 --- a/services/register/register_service/db/db.py +++ b/services/register/register_service/db/db.py @@ -1,9 +1,7 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config -from bson.codec_options import CodecOptions +from config import Config class MongoDatabse(): diff --git a/services/register/register_service/wsgi.py b/services/register/register_service/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/register/register_service/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/register/requirements.txt b/services/register/requirements.txt index c5446a6bfcd8efcd5623e685b22fe6f2eac48c46..8da8ad4d2a954b95ab42c32773ffdf558b499b3d 100644 --- a/services/register/requirements.txt +++ b/services/register/requirements.txt @@ -2,6 +2,8 @@ python_dateutil >= 2.6.0 setuptools >= 21.0.0 Flask >= 2.0.3 pymongo == 4.0.1 +gunicorn==22.0.0 +packaging==24.0 flask_jwt_extended pyopenssl pyyaml