From 8cdc9b112ec37ce4343017d7fe6dda5a06a0a7b7 Mon Sep 17 00:00:00 2001 From: Jorge Moratinos Salcines Date: Fri, 12 Jan 2024 12:21:35 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 46 + CITATION.cff | 9 + FAQ.md | 88 + LICENSE | 201 + README.md | 198 +- cicd/exclusions | 5 + cicd/ruff.toml | 3 + docs/images/flows/01 - Register del AEF.png | Bin 0 -> 71533 bytes .../02 - AEF API Provider registration.png | Bin 0 -> 49215 bytes docs/images/flows/03 - AEF Publish.png | Bin 0 -> 43268 bytes docs/images/flows/04 - Invoker Register.png | Bin 0 -> 71642 bytes docs/images/flows/05 - Invoker Onboarding.png | Bin 0 -> 64059 bytes .../flows/06 - Invoker Discover AEF.png | Bin 0 -> 43087 bytes .../07 - Invoker Create Security Context.png | Bin 0 -> 43568 bytes docs/images/flows/08 - Invoker Get Token.png | Bin 0 -> 55546 bytes ...nvoker Send Request to AEF Service API.png | Bin 0 -> 26214 bytes docs/images/robot_log_example.png | Bin 0 -> 158079 bytes docs/images/robot_report_example.png | Bin 0 -> 183065 bytes docs/test_plan/README.md | 16 + .../api_access_control_policy/README.md | 813 ++++ .../service_api_description_post_example.json | 113 + docs/test_plan/api_auditing_service/README.md | 244 ++ docs/test_plan/api_discover_service/README.md | 336 ++ docs/test_plan/api_events_service/README.md | 265 ++ .../event_subscription.json | 31 + .../api_invoker_management/README.md | 306 ++ .../invoker_details_post_example.json | 15 + .../invoker_details_put_example.json | 393 ++ .../invoker_getauth_example.json | 4 + .../invoker_register_body.json | 7 + docs/test_plan/api_logging_service/README.md | 241 ++ .../api_logging_service/invocation_log.json | 45 + .../api_provider_management/README.md | 398 ++ ...tails_enrolment_details_patch_example.json | 29 + .../provider_details_post_example.json | 17 + .../provider_getauth_example.json | 4 + .../provider_register_body.json | 7 + docs/test_plan/api_publish_service/README.md | 599 +++ .../publisher_register_body.json | 7 + .../service_api_description_post_example.json | 113 + docs/test_plan/api_security_service/README.md | 1244 +++++++ .../access_token_req.json | 6 + .../access_token_req_example.json | 5 + .../security_notification.json | 9 + .../service_security.json | 25 + docs/test_plan/common_operations/README.md | 86 + docs/testing_with_curl/README.md | 369 ++ .../capif_tls_curls_exposer.sh | 205 + .../capif_tls_curls_invoker.sh | 86 + docs/testing_with_curl/exposer.key | 28 + docs/testing_with_curl/invoker.key | 28 + .../CAPIF.postman_collection.json | 982 +++++ .../CAPIF.postman_environment.json | 237 ++ docs/testing_with_postman/README.md | 108 + docs/testing_with_postman/hello_api.py | 38 + docs/testing_with_postman/package.json | 16 + docs/testing_with_postman/script.js | 199 + docs/testing_with_robot/README.md | 74 + helm/README-vault.md | 52 + helm/README.md | 47 + helm/capif/.helmignore | 23 + helm/capif/Chart.yaml | 26 + helm/capif/README.md | 304 ++ helm/capif/docker-monitoring.json | 690 ++++ helm/capif/kubernetes-dashboard.json | 2629 +++++++++++++ helm/capif/loki-logs.json | 281 ++ helm/capif/templates/_helpers.tpl | 62 + .../templates/access-control-policy.yaml | 17 + helm/capif/templates/api-invocation-logs.yaml | 17 + .../templates/api-invoker-management.yaml | 17 + .../templates/api-provider-management.yaml | 17 + .../templates/capif-events-configmap.yaml | 28 + helm/capif/templates/capif-events.yaml | 17 + .../templates/capif-invocation-configmap.yaml | 29 + .../templates/capif-invoker-configmap.yaml | 41 + .../capif/templates/capif-logs-configmap.yaml | 27 + .../templates/capif-provider-configmap.yaml | 41 + .../templates/capif-published-configmap.yaml | 27 + helm/capif/templates/capif-routing-info.yaml | 17 + .../templates/capif-security-configmap.yaml | 28 + helm/capif/templates/capif-security.yaml | 17 + .../templates/capif-service-configmap.yaml | 27 + helm/capif/templates/deployment.yaml | 1001 +++++ helm/capif/templates/fluent-bit-service.yaml | 24 + helm/capif/templates/fluentbit-configmap.yaml | 24 + .../capif/templates/fluentbit-deployment.yaml | 59 + helm/capif/templates/grafana-configmap.yaml | 108 + helm/capif/templates/grafana-deployment.yaml | 109 + .../templates/grafana-ingress-route.yaml | 18 + helm/capif/templates/grafana-ingress.yaml | 34 + helm/capif/templates/grafana-pvc.yaml | 16 + helm/capif/templates/grafana-secrets.yaml | 10 + helm/capif/templates/grafana-service.yaml | 17 + helm/capif/templates/logs.yaml | 17 + helm/capif/templates/loki-deployment.yaml | 54 + helm/capif/templates/loki-pvc.yaml | 16 + helm/capif/templates/loki-service.yaml | 19 + helm/capif/templates/mongo-express.yaml | 17 + helm/capif/templates/mongo-pvc.yaml | 16 + helm/capif/templates/mongo-register.yaml | 17 + helm/capif/templates/mongo.yaml | 17 + helm/capif/templates/nginx-ingress-route.yaml | 17 + .../templates/nginx-ssl-ingress-route.yaml | 18 + helm/capif/templates/nginx-ssl-route.yaml | 22 + helm/capif/templates/nginx-ssl.yaml | 32 + helm/capif/templates/nginx.yaml | 48 + .../templates/otel-collector-configmap.yaml | 37 + .../templates/otel-collector-deployment.yaml | 54 + .../templates/otel-collector-service.yaml | 22 + .../templates/prometheus-clusterrole.yaml | 49 + .../capif/templates/prometheus-configmap.yaml | 141 + .../templates/prometheus-deployment.yaml | 68 + .../templates/prometheus-ingress-route.yaml | 20 + helm/capif/templates/prometheus-ingress.yaml | 36 + helm/capif/templates/prometheus-pvc.yaml | 19 + helm/capif/templates/prometheus-service.yaml | 22 + helm/capif/templates/published-apis.yaml | 17 + helm/capif/templates/redis.yaml | 17 + helm/capif/templates/register-configmap.yaml | 21 + helm/capif/templates/register.yaml | 19 + helm/capif/templates/renderer-configmap.yaml | 8 + helm/capif/templates/renderer-deployment.yaml | 44 + helm/capif/templates/renderer-service.yaml | 18 + helm/capif/templates/service-apis.yaml | 17 + helm/capif/values.yaml | 660 ++++ helm/helmfile-capif.yaml | 19 + helm/vault-job/vault-job.yaml | 251 ++ monitoring/docker-compose.yml | 110 + monitoring/fluent_bit/fluent-bit.conf | 15 + monitoring/grafana/grafana_config/grafana.ini | 1894 ++++++++++ .../grafana_dashboards/Docker-monitoring.json | 690 ++++ .../grafana/grafana_dashboards/Loki-Logs.json | 281 ++ .../grafana-datasources.yaml | 54 + .../grafana-default-provisioning.yaml | 14 + .../provisioning/dashboards/default.yaml | 0 .../provisioning/datasources/datasources.yaml | 0 monitoring/otlp_collector/otel-config.yaml | 26 + monitoring/prometheus/prometheus.yml | 19 + monitoring/tempo/tempo.yaml | 46 + prometheus/kustomization.yaml | 11 + ...ometheus-claim1-persistentvolumeclaim.yaml | 14 + ...ometheus-claim2-persistentvolumeclaim.yaml | 14 + ...ometheus-claim3-persistentvolumeclaim.yaml | 14 + ...ometheus-claim4-persistentvolumeclaim.yaml | 14 + prometheus/prometheus-configmap.yaml | 38 + prometheus/prometheus-deployment.yaml | 71 + prometheus/prometheus-service.yaml | 19 + services/.env | 24 + .../.dockerignore | 72 + .../.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 46 + .../.openapi-generator/VERSION | 1 + .../.travis.yml | 14 + .../Dockerfile | 18 + .../README.md | 49 + .../api_invoker_management/__init__.py | 0 .../api_invoker_management/__main__.py | 152 + .../api_invoker_management/config.py | 21 + .../controllers/__init__.py | 0 .../controllers/default_controller.py | 123 + .../controllers/security_controller_.py | 2 + .../core/apiinvokerenrolmentdetails.py | 159 + .../core/auth_manager.py | 25 + .../core/consumer_messager.py | 26 + .../core/invoker_internal_ops.py | 40 + .../api_invoker_management/core/publisher.py | 11 + .../api_invoker_management/core/resources.py | 7 + .../api_invoker_management/core/responses.py | 31 + .../core/validate_user.py | 26 + .../api_invoker_management/db/db.py | 76 + .../api_invoker_management/encoder.py | 20 + .../api_invoker_management/models/__init__.py | 29 + .../models/aef_profile.py | 250 ++ .../models/api_invoker_enrolment_details.py | 271 ++ .../models/base_model_.py | 69 + .../models/communication_type.py | 39 + .../models/communication_type_any_of.py | 42 + .../models/custom_operation.py | 158 + .../models/data_format.py | 39 + .../models/data_format_any_of.py | 41 + .../models/interface_description.py | 158 + .../models/invalid_param.py | 96 + .../models/onboarding_information.py | 124 + .../models/onboarding_notification.py | 156 + .../models/operation.py | 39 + .../models/operation_any_of.py | 45 + .../models/problem_details.py | 270 ++ .../api_invoker_management/models/protocol.py | 39 + .../models/protocol_any_of.py | 42 + .../models/published_api_path.py | 68 + .../api_invoker_management/models/resource.py | 216 ++ .../models/security_method.py | 39 + .../models/security_method_any_of.py | 43 + .../models/service_api_description.py | 328 ++ .../models/shareable_information.py | 98 + .../api_invoker_management/models/version.py | 160 + .../models/websock_notif_config.py | 94 + .../openapi/openapi.yaml | 2448 ++++++++++++ .../api_invoker_management/typing_utils.py | 32 + .../api_invoker_management/util.py | 172 + .../config.yaml | 35 + .../git_push.sh | 57 + .../prepare_invoker.sh | 18 + .../requirements.txt | 21 + .../setup.py | 39 + .../test-requirements.txt | 4 + .../tox.ini | 11 + .../.dockerignore | 72 + .../.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 29 + .../.openapi-generator/VERSION | 1 + .../.travis.yml | 14 + .../Dockerfile | 18 + .../README.md | 49 + .../api_provider_management/__init__.py | 0 .../api_provider_management/__main__.py | 136 + .../api_provider_management/config.py | 18 + .../controllers/__init__.py | 0 .../controllers/default_controller.py | 115 + ...i_provider_enrolment_details_controller.py | 38 + .../controllers/security_controller_.py | 2 + .../core/auth_manager.py | 27 + .../core/provider_enrolment_details_api.py | 169 + .../api_provider_management/core/publisher.py | 10 + .../api_provider_management/core/resources.py | 9 + .../api_provider_management/core/responses.py | 31 + .../core/sign_certificate.py | 22 + .../core/validate_user.py | 26 + .../api_provider_management/db/db.py | 73 + .../api_provider_management/encoder.py | 20 + .../models/__init__.py | 13 + .../models/api_provider_enrolment_details.py | 216 ++ .../api_provider_enrolment_details_patch.py | 98 + .../models/api_provider_func_role.py | 39 + .../models/api_provider_func_role_any_of.py | 43 + .../models/api_provider_function_details.py | 154 + .../models/base_model_.py | 69 + .../models/invalid_param.py | 96 + .../models/problem_details.py | 270 ++ .../models/registration_information.py | 96 + .../openapi/openapi.yaml | 619 +++ .../api_provider_management/typing_utils.py | 32 + .../api_provider_management/util.py | 183 + .../config.yaml | 37 + .../git_push.sh | 57 + .../prepare_provider.sh | 19 + .../requirements.txt | 21 + .../setup.py | 39 + .../test-requirements.txt | 4 + .../tox.ini | 11 + .../.dockerignore | 72 + .../.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 28 + .../.openapi-generator/VERSION | 1 + .../.travis.yml | 14 + .../Dockerfile | 16 + .../README.md | 49 + .../config.yaml | 30 + .../git_push.sh | 57 + .../openapi_server/__init__.py | 0 .../openapi_server/__main__.py | 149 + .../openapi_server/config.py | 21 + .../openapi_server/controllers/__init__.py | 0 .../controllers/default_controller.py | 46 + .../controllers/security_controller_.py | 2 + .../core/accesscontrolpolicyapi.py | 54 + .../openapi_server/core/consumer_messager.py | 37 + .../core/internal_service_ops.py | 85 + .../openapi_server/core/publisher.py | 11 + .../openapi_server/core/resources.py | 7 + .../openapi_server/core/responses.py | 31 + .../openapi_server/db/db.py | 46 + .../openapi_server/encoder.py | 20 + .../openapi_server/models/__init__.py | 10 + .../models/access_control_policy_list.py | 70 + .../models/api_invoker_policy.py | 156 + .../openapi_server/models/base_model_.py | 69 + .../openapi_server/models/invalid_param.py | 96 + .../openapi_server/models/problem_details.py | 270 ++ .../openapi_server/models/time_range_list.py | 94 + .../openapi_server/openapi/openapi.yaml | 375 ++ .../openapi_server/test/__init__.py | 16 + .../test/test_default_controller.py | 38 + .../openapi_server/typing_utils.py | 32 + .../openapi_server/util.py | 186 + .../requirements.txt | 29 + .../setup.py | 39 + .../test-requirements.txt | 4 + .../tox.ini | 11 + .../TS29222_CAPIF_Auditing_API/.dockerignore | 72 + .../TS29222_CAPIF_Auditing_API/.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 33 + .../.openapi-generator/VERSION | 1 + .../TS29222_CAPIF_Auditing_API/.travis.yml | 14 + .../TS29222_CAPIF_Auditing_API/Dockerfile | 17 + services/TS29222_CAPIF_Auditing_API/README.md | 49 + .../TS29222_CAPIF_Auditing_API/config.yaml | 20 + .../TS29222_CAPIF_Auditing_API/git_push.sh | 57 + .../logs/__init__.py | 0 .../logs/__main__.py | 116 + .../TS29222_CAPIF_Auditing_API/logs/config.py | 20 + .../logs/controllers/__init__.py | 0 .../logs/controllers/default_controller.py | 88 + .../logs/controllers/security_controller_.py | 2 + .../logs/core/auditoperations.py | 71 + .../logs/core/resources.py | 8 + .../logs/core/responses.py | 36 + .../TS29222_CAPIF_Auditing_API/logs/db/db.py | 43 + .../logs/encoder.py | 20 + .../logs/models/__init__.py | 16 + .../logs/models/base_model_.py | 69 + .../logs/models/interface_description.py | 158 + .../logs/models/invalid_param.py | 96 + .../logs/models/invocation_log.py | 164 + .../logs/models/log.py | 470 +++ .../logs/models/operation.py | 45 + .../logs/models/operation_any_of.py | 45 + .../logs/models/problem_details.py | 270 ++ .../logs/models/protocol.py | 42 + .../logs/models/protocol_any_of.py | 42 + .../logs/models/security_method.py | 42 + .../logs/models/security_method_any_of.py | 43 + .../logs/openapi/openapi.yaml | 664 ++++ .../logs/typing_utils.py | 32 + .../TS29222_CAPIF_Auditing_API/logs/util.py | 186 + .../requirements.txt | 20 + services/TS29222_CAPIF_Auditing_API/setup.py | 39 + .../test-requirements.txt | 4 + services/TS29222_CAPIF_Auditing_API/tox.ini | 11 + .../.dockerignore | 72 + .../.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 43 + .../.openapi-generator/VERSION | 1 + .../.travis.yml | 14 + .../Dockerfile | 17 + .../README.md | 49 + .../config.yaml | 21 + .../git_push.sh | 57 + .../requirements.txt | 22 + .../service_apis/__init__.py | 0 .../service_apis/__main__.py | 131 + .../service_apis/config.py | 20 + .../service_apis/controllers/__init__.py | 0 .../controllers/default_controller.py | 48 + .../controllers/security_controller_.py | 2 + .../service_apis/core/discoveredapis.py | 65 + .../service_apis/core/resources.py | 7 + .../service_apis/core/responses.py | 32 + .../service_apis/db/db.py | 44 + .../service_apis/encoder.py | 20 + .../service_apis/models/__init__.py | 26 + .../service_apis/models/aef_profile.py | 250 ++ .../service_apis/models/base_model_.py | 69 + .../service_apis/models/communication_type.py | 39 + .../models/communication_type_any_of.py | 42 + .../service_apis/models/custom_operation.py | 158 + .../service_apis/models/data_format.py | 39 + .../service_apis/models/data_format_any_of.py | 41 + .../service_apis/models/discovered_apis.py | 70 + .../models/interface_description.py | 158 + .../service_apis/models/invalid_param.py | 96 + .../service_apis/models/operation.py | 39 + .../service_apis/models/operation_any_of.py | 45 + .../service_apis/models/problem_details.py | 270 ++ .../service_apis/models/protocol.py | 39 + .../service_apis/models/protocol_any_of.py | 42 + .../service_apis/models/published_api_path.py | 68 + .../service_apis/models/resource.py | 216 ++ .../service_apis/models/security_method.py | 39 + .../models/security_method_any_of.py | 43 + .../models/service_api_description.py | 328 ++ .../models/shareable_information.py | 98 + .../service_apis/models/version.py | 160 + .../service_apis/openapi/openapi.yaml | 1330 +++++++ .../service_apis/typing_utils.py | 32 + .../service_apis/util.py | 190 + .../setup.py | 39 + .../test-requirements.txt | 4 + .../tox.ini | 11 + .../TS29222_CAPIF_Events_API/.dockerignore | 72 + services/TS29222_CAPIF_Events_API/.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 67 + .../.openapi-generator/VERSION | 1 + services/TS29222_CAPIF_Events_API/.travis.yml | 14 + services/TS29222_CAPIF_Events_API/Dockerfile | 18 + services/TS29222_CAPIF_Events_API/README.md | 49 + .../capif_events/__init__.py | 0 .../capif_events/__main__.py | 151 + .../capif_events/config.py | 18 + .../capif_events/controllers/__init__.py | 0 .../controllers/default_controller.py | 82 + .../controllers/security_controller_.py | 2 + .../capif_events/core/auth_manager.py | 63 + .../capif_events/core/consumer_messager.py | 33 + .../capif_events/core/events_apis.py | 121 + .../capif_events/core/internal_event_ops.py | 59 + .../capif_events/core/notifications.py | 43 + .../capif_events/core/resources.py | 7 + .../capif_events/core/responses.py | 31 + .../capif_events/core/validate_user.py | 26 + .../capif_events/db/db.py | 48 + .../capif_events/encoder.py | 20 + .../capif_events/models/__init__.py | 50 + .../models/access_control_policy_list.py | 70 + .../models/access_control_policy_list_ext.py | 102 + .../access_control_policy_list_ext_all_of.py | 64 + .../capif_events/models/aef_profile.py | 250 ++ .../capif_events/models/api_invoker_policy.py | 156 + .../capif_events/models/base_model_.py | 69 + .../capif_events/models/capif_event.py | 39 + .../capif_events/models/capif_event_any_of.py | 53 + .../capif_events/models/capif_event_detail.py | 218 ++ .../capif_events/models/capif_event_filter.py | 128 + .../capif_events/models/communication_type.py | 39 + .../models/communication_type_any_of.py | 42 + .../capif_events/models/custom_operation.py | 158 + .../capif_events/models/data_format.py | 39 + .../capif_events/models/data_format_any_of.py | 41 + .../capif_events/models/event_notification.py | 126 + .../capif_events/models/event_subscription.py | 250 ++ .../models/interface_description.py | 158 + .../capif_events/models/invalid_param.py | 96 + .../capif_events/models/invocation_log.py | 164 + .../capif_events/models/ipv4_address_range.py | 100 + .../capif_events/models/ipv6_address_range.py | 98 + .../capif_events/models/log.py | 470 +++ .../capif_events/models/notification_flag.py | 39 + .../models/notification_flag_any_of.py | 43 + .../models/notification_method.py | 39 + .../models/notification_method_any_of.py | 43 + .../capif_events/models/operation.py | 39 + .../capif_events/models/operation_any_of.py | 45 + .../models/partitioning_criteria.py | 39 + .../models/partitioning_criteria_any_of.py | 45 + .../capif_events/models/problem_details.py | 270 ++ .../capif_events/models/protocol.py | 39 + .../capif_events/models/protocol_any_of.py | 42 + .../capif_events/models/published_api_path.py | 68 + .../models/reporting_information.py | 298 ++ .../capif_events/models/resource.py | 216 ++ .../capif_events/models/routing_rule.py | 128 + .../capif_events/models/security_method.py | 39 + .../models/security_method_any_of.py | 43 + .../models/service_api_description.py | 328 ++ .../models/shareable_information.py | 98 + .../capif_events/models/time_range_list.py | 94 + .../capif_events/models/topology_hiding.py | 98 + .../capif_events/models/version.py | 160 + .../models/websock_notif_config.py | 94 + .../capif_events/openapi/openapi.yaml | 3314 +++++++++++++++++ .../capif_events/typing_utils.py | 32 + .../capif_events/util.py | 175 + services/TS29222_CAPIF_Events_API/config.yaml | 23 + services/TS29222_CAPIF_Events_API/git_push.sh | 57 + .../TS29222_CAPIF_Events_API/requirements.txt | 23 + services/TS29222_CAPIF_Events_API/setup.py | 39 + .../test-requirements.txt | 4 + services/TS29222_CAPIF_Events_API/tox.ini | 11 + .../.dockerignore | 72 + .../.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 33 + .../.openapi-generator/VERSION | 1 + .../.travis.yml | 14 + .../Dockerfile | 17 + .../README.md | 49 + .../api_invocation_logs/__init__.py | 0 .../api_invocation_logs/__main__.py | 120 + .../api_invocation_logs/config.py | 20 + .../controllers/__init__.py | 0 .../controllers/default_controller.py | 69 + .../controllers/security_controller_.py | 2 + .../core/invocationlogs.py | 121 + .../api_invocation_logs/core/resources.py | 8 + .../api_invocation_logs/core/responses.py | 43 + .../api_invocation_logs/core/validate_user.py | 26 + .../api_invocation_logs/db/db.py | 46 + .../api_invocation_logs/encoder.py | 20 + .../api_invocation_logs/models/__init__.py | 16 + .../api_invocation_logs/models/base_model_.py | 69 + .../models/interface_description.py | 158 + .../models/invalid_param.py | 96 + .../models/invocation_log.py | 164 + .../api_invocation_logs/models/log.py | 470 +++ .../api_invocation_logs/models/operation.py | 39 + .../models/operation_any_of.py | 45 + .../models/problem_details.py | 270 ++ .../api_invocation_logs/models/protocol.py | 39 + .../models/protocol_any_of.py | 42 + .../models/security_method.py | 39 + .../models/security_method_any_of.py | 43 + .../api_invocation_logs/openapi/openapi.yaml | 524 +++ .../api_invocation_logs/typing_utils.py | 32 + .../api_invocation_logs/util.py | 186 + .../config.yaml | 23 + .../git_push.sh | 57 + .../requirements.txt | 20 + .../setup.py | 39 + .../test-requirements.txt | 4 + .../tox.ini | 11 + .../.dockerignore | 72 + .../.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 42 + .../.openapi-generator/VERSION | 1 + .../.travis.yml | 14 + .../Dockerfile | 17 + .../README.md | 49 + .../config.yaml | 21 + .../git_push.sh | 57 + .../published_apis/__init__.py | 0 .../published_apis/__main__.py | 142 + .../published_apis/config.py | 21 + .../published_apis/controllers/__init__.py | 0 .../controllers/default_controller.py | 160 + .../controllers/security_controller_.py | 2 + .../published_apis/core/auth_manager.py | 47 + .../published_apis/core/consumer_messager.py | 29 + .../core/internal_service_ops.py | 22 + .../published_apis/core/publisher.py | 10 + .../published_apis/core/resources.py | 7 + .../published_apis/core/responses.py | 37 + .../core/serviceapidescriptions.py | 218 ++ .../published_apis/core/validate_user.py | 26 + .../published_apis/db/db.py | 45 + .../published_apis/encoder.py | 20 + .../published_apis/models/__init__.py | 25 + .../published_apis/models/aef_profile.py | 250 ++ .../published_apis/models/base_model_.py | 69 + .../models/communication_type.py | 39 + .../models/communication_type_any_of.py | 42 + .../published_apis/models/custom_operation.py | 158 + .../published_apis/models/data_format.py | 39 + .../models/data_format_any_of.py | 41 + .../models/interface_description.py | 158 + .../published_apis/models/invalid_param.py | 96 + .../published_apis/models/operation.py | 39 + .../published_apis/models/operation_any_of.py | 45 + .../published_apis/models/problem_details.py | 270 ++ .../published_apis/models/protocol.py | 39 + .../published_apis/models/protocol_any_of.py | 42 + .../models/published_api_path.py | 68 + .../published_apis/models/resource.py | 216 ++ .../published_apis/models/security_method.py | 39 + .../models/security_method_any_of.py | 43 + .../models/service_api_description.py | 328 ++ .../models/shareable_information.py | 98 + .../published_apis/models/version.py | 160 + .../published_apis/openapi/openapi.yaml | 1285 +++++++ .../published_apis/typing_utils.py | 32 + .../published_apis/util.py | 187 + .../requirements.txt | 21 + .../setup.py | 39 + .../test-requirements.txt | 4 + .../TS29222_CAPIF_Publish_Service_API/tox.ini | 11 + .../.dockerignore | 72 + .../TS29222_CAPIF_Routing_Info_API/.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 43 + .../.openapi-generator/VERSION | 1 + .../.travis.yml | 14 + .../TS29222_CAPIF_Routing_Info_API/Dockerfile | 16 + .../TS29222_CAPIF_Routing_Info_API/README.md | 49 + .../capif_routing_info/__init__.py | 0 .../capif_routing_info/__main__.py | 19 + .../controllers/__init__.py | 0 .../controllers/default_controller.py | 23 + .../controllers/security_controller_.py | 2 + .../capif_routing_info/encoder.py | 20 + .../capif_routing_info/models/__init__.py | 26 + .../capif_routing_info/models/aef_profile.py | 250 ++ .../capif_routing_info/models/base_model_.py | 69 + .../models/communication_type.py | 39 + .../models/communication_type_any_of.py | 42 + .../models/custom_operation.py | 158 + .../capif_routing_info/models/data_format.py | 39 + .../models/data_format_any_of.py | 41 + .../models/interface_description.py | 158 + .../models/invalid_param.py | 96 + .../models/ipv4_address_range.py | 100 + .../models/ipv6_address_range.py | 98 + .../capif_routing_info/models/operation.py | 39 + .../models/operation_any_of.py | 45 + .../models/problem_details.py | 270 ++ .../capif_routing_info/models/protocol.py | 39 + .../models/protocol_any_of.py | 42 + .../capif_routing_info/models/resource.py | 216 ++ .../capif_routing_info/models/routing_info.py | 70 + .../capif_routing_info/models/routing_rule.py | 128 + .../models/security_method.py | 39 + .../models/security_method_any_of.py | 43 + .../capif_routing_info/models/version.py | 160 + .../capif_routing_info/openapi/openapi.yaml | 972 +++++ .../capif_routing_info/test/__init__.py | 16 + .../test/test_default_controller.py | 37 + .../capif_routing_info/typing_utils.py | 32 + .../capif_routing_info/util.py | 148 + .../git_push.sh | 57 + .../requirements.txt | 5 + .../TS29222_CAPIF_Routing_Info_API/setup.py | 39 + .../test-requirements.txt | 4 + .../TS29222_CAPIF_Routing_Info_API/tox.ini | 11 + .../TS29222_CAPIF_Security_API/.dockerignore | 72 + .../TS29222_CAPIF_Security_API/.gitignore | 66 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 36 + .../.openapi-generator/VERSION | 1 + .../TS29222_CAPIF_Security_API/.travis.yml | 14 + .../TS29222_CAPIF_Security_API/Dockerfile | 18 + services/TS29222_CAPIF_Security_API/README.md | 49 + .../capif_security/__init__.py | 0 .../capif_security/__main__.py | 148 + .../capif_security/config.py | 21 + .../capif_security/controllers/__init__.py | 0 .../controllers/default_controller.py | 191 + .../controllers/security_controller_.py | 2 + .../capif_security/core/consumer_messager.py | 32 + .../core/internal_security_ops.py | 22 + .../capif_security/core/notification.py | 14 + .../capif_security/core/publisher.py | 10 + .../capif_security/core/resources.py | 9 + .../capif_security/core/responses.py | 37 + .../capif_security/core/servicesecurity.py | 376 ++ .../capif_security/core/validate_user.py | 26 + .../capif_security/db/db.py | 46 + .../capif_security/encoder.py | 20 + .../capif_security/models/__init__.py | 28 + .../models/access_token_claims.py | 126 + .../capif_security/models/access_token_err.py | 122 + .../models/access_token_err1.py | 122 + .../capif_security/models/access_token_req.py | 151 + .../models/access_token_req1.py | 559 +++ .../capif_security/models/access_token_rsp.py | 158 + .../capif_security/models/base_model_.py | 69 + .../capif_security/models/cause.py | 39 + .../capif_security/models/cause_any_of.py | 42 + .../models/interface_description.py | 158 + .../capif_security/models/invalid_param.py | 96 + .../capif_security/models/invalid_param1.py | 96 + .../capif_security/models/nf_type.py | 39 + .../capif_security/models/nf_type_any_of.py | 95 + .../capif_security/models/plmn_id.py | 104 + .../capif_security/models/plmn_id_nid.py | 134 + .../capif_security/models/problem_details.py | 270 ++ .../capif_security/models/problem_details1.py | 354 ++ .../models/security_information.py | 239 ++ .../capif_security/models/security_method.py | 41 + .../models/security_method_any_of.py | 44 + .../models/security_notification.py | 158 + .../capif_security/models/service_security.py | 186 + .../capif_security/models/snssai.py | 104 + .../models/websock_notif_config.py | 94 + .../capif_security/openapi/openapi.yaml | 1729 +++++++++ .../capif_security/typing_utils.py | 32 + .../capif_security/util.py | 186 + .../TS29222_CAPIF_Security_API/config.yaml | 22 + .../TS29222_CAPIF_Security_API/git_push.sh | 57 + services/TS29222_CAPIF_Security_API/main.py | 61 + .../requirements.txt | 22 + .../security_prepare.sh | 19 + services/TS29222_CAPIF_Security_API/setup.py | 39 + .../test-requirements.txt | 4 + services/TS29222_CAPIF_Security_API/tox.ini | 11 + .../CAPIFInvokerGUI/invoker_gui/Dockerfile | 13 + .../invoker_gui/capif_ops/__init__.py | 0 .../config_files/capif_registration.json | 17 + .../config_files/credentials.properties | 14 + .../capif_ops/config_files/demo_values.json | 1 + .../capif_ops/config_files/events.json | 6 + .../config_files/invoker_details.json | 13 + .../capif_ops/config_files/security_info.json | 18 + .../config_files/service_request_body.json | 32 + .../capif_ops/config_files/token_request.json | 6 + .../invoker_gui/capif_ops/invoker_delete.py | 71 + .../capif_ops/invoker_discover_service.py | 96 + .../invoker_gui/capif_ops/invoker_get_auth.py | 71 + .../capif_ops/invoker_get_security_auth.py | 90 + .../capif_ops/invoker_previous_register.py | 134 + .../capif_ops/invoker_register_to_capif.py | 134 + .../invoker_remove_security_context.py | 82 + .../capif_ops/invoker_secutiry_context.py | 96 + .../capif_ops/invoker_to_service.py | 168 + .../capif_ops/nef_calback_server/__init__.py | 0 .../capif_ops/nef_calback_server/callback.py | 26 + .../CAPIFInvokerGUI/invoker_gui/main.py | 98 + .../CAPIFInvokerGUI/invoker_gui/prepare.sh | 11 + .../invoker_gui/requirements.txt | 13 + services/capif-client/Dockerfile | 5 + services/check_services_are_running.sh | 12 + services/clean_capif_docker_services.sh | 40 + services/docker-compose-capif.yml | 259 ++ services/docker-compose-register.yml | 51 + services/docker-compose-vault.yml | 16 + .../docker-compose/docker-compose-capif.yml | 246 ++ .../docker-compose-montoring.yml | 110 + .../docker-compose-register.yml | 37 + .../docker-compose/docker-compose-vault.yml | 16 + services/docker-compose/run.sh | 91 + services/docker-compose/stop.sh | 98 + services/nginx/Dockerfile | 16 + services/nginx/certs/sign_req_body_tmp.json | 5 + services/nginx/nginx.conf | 169 + services/nginx/nginx_prepare.sh | 38 + services/register/.gitignore | 66 + services/register/Dockerfile | 18 + services/register/config.yaml | 14 + services/register/register_prepare.sh | 55 + .../register/register_service/__init__.py | 0 .../register/register_service/__main__.py | 27 + services/register/register_service/config.py | 20 + .../controllers/register_controller.py | 39 + .../core/register_operations.py | 71 + services/register/register_service/db/db.py | 38 + services/register/requirements.txt | 8 + services/run.sh | 91 + services/runCapifTests.sh | 52 + services/stop.sh | 98 + services/vault/Dockerfile | 12 + services/vault/vault_prepare_certs.sh | 138 + .../__init__.robot | 2 + .../capif_api_access_control_policy.robot | 627 ++++ .../CAPIF Api Auditing Service/__init__.robot | 2 + .../capif_auditing_api.robot | 243 ++ .../CAPIF Api Discover Service/__init__.robot | 2 + .../capif_api_service_discover.robot | 257 ++ .../features/CAPIF Api Events/__init__.robot | 2 + .../CAPIF Api Events/capif_events_api.robot | 156 + .../__init__.robot | 2 + .../capif_api_invoker_managenet.robot | 201 + .../CAPIF Api Logging Service/__init__.robot | 2 + .../capif_logging_api.robot | 221 ++ .../__init__.robot | 2 + .../capif_api_provider_management.robot | 222 ++ .../CAPIF Api Publish Service/__init__.robot | 2 + .../capif_api_publish_service.robot | 374 ++ .../CAPIF Security Api/__init__.robot | 2 + .../capif_security_api.robot | 1192 ++++++ tests/features/__init__.robot | 56 + tests/libraries/api_events/bodyRequests.py | 32 + .../api_invoker_management/bodyRequests.py | 20 + .../api_logging_service/bodyRequests.py | 133 + .../api_provider_management/bodyRequests.py | 41 + .../api_publish_service/bodyRequests.py | 68 + tests/libraries/bodyRequests.py | 8 + tests/libraries/common/bodyRequests.py | 125 + tests/libraries/common/types.json | 606 +++ tests/libraries/environment.py | 25 + tests/libraries/helpers.py | 141 + tests/libraries/security_api/bodyRequests.py | 96 + tests/requirements.txt | 7 + .../apiInvokerManagementRequests.robot | 4 + tests/resources/common.resource | 84 + tests/resources/common/basicRequests.robot | 593 +++ tests/resources/common/httpServer.robot | 2 + tests/resources/common/httpServerCtrl.robot | 3 + .../generate_all_capif_apis.sh | 92 + tools/robot/Dockerfile | 100 + tools/robot/README.md | 37 + tools/robot/basicRequirements.txt | 101 + tools/robot/basicRobotInstall.sh | 7 + tools/robot/doc_entrypoint.sh | 48 + tools/robot/entrypoint.sh | 48 + tools/robot/featdoc_entrypoint.sh | 48 + tools/robot/libdoc_entrypoint.sh | 48 + tools/robot/linter_entrypoint.sh | 48 + 771 files changed, 77973 insertions(+), 57 deletions(-) create mode 100644 .gitignore create mode 100644 CITATION.cff create mode 100644 FAQ.md create mode 100644 LICENSE create mode 100644 cicd/exclusions create mode 100644 cicd/ruff.toml create mode 100644 docs/images/flows/01 - Register del AEF.png create mode 100644 docs/images/flows/02 - AEF API Provider registration.png create mode 100644 docs/images/flows/03 - AEF Publish.png create mode 100644 docs/images/flows/04 - Invoker Register.png create mode 100644 docs/images/flows/05 - Invoker Onboarding.png create mode 100644 docs/images/flows/06 - Invoker Discover AEF.png create mode 100644 docs/images/flows/07 - Invoker Create Security Context.png create mode 100644 docs/images/flows/08 - Invoker Get Token.png create mode 100644 docs/images/flows/09 - Invoker Send Request to AEF Service API.png create mode 100644 docs/images/robot_log_example.png create mode 100644 docs/images/robot_report_example.png create mode 100644 docs/test_plan/README.md create mode 100644 docs/test_plan/api_access_control_policy/README.md create mode 100644 docs/test_plan/api_access_control_policy/service_api_description_post_example.json create mode 100644 docs/test_plan/api_auditing_service/README.md create mode 100644 docs/test_plan/api_discover_service/README.md create mode 100644 docs/test_plan/api_events_service/README.md create mode 100644 docs/test_plan/api_events_service/event_subscription.json create mode 100644 docs/test_plan/api_invoker_management/README.md create mode 100644 docs/test_plan/api_invoker_management/invoker_details_post_example.json create mode 100644 docs/test_plan/api_invoker_management/invoker_details_put_example.json create mode 100644 docs/test_plan/api_invoker_management/invoker_getauth_example.json create mode 100644 docs/test_plan/api_invoker_management/invoker_register_body.json create mode 100644 docs/test_plan/api_logging_service/README.md create mode 100644 docs/test_plan/api_logging_service/invocation_log.json create mode 100644 docs/test_plan/api_provider_management/README.md create mode 100644 docs/test_plan/api_provider_management/provider_details_enrolment_details_patch_example.json create mode 100644 docs/test_plan/api_provider_management/provider_details_post_example.json create mode 100644 docs/test_plan/api_provider_management/provider_getauth_example.json create mode 100644 docs/test_plan/api_provider_management/provider_register_body.json create mode 100644 docs/test_plan/api_publish_service/README.md create mode 100644 docs/test_plan/api_publish_service/publisher_register_body.json create mode 100644 docs/test_plan/api_publish_service/service_api_description_post_example.json create mode 100644 docs/test_plan/api_security_service/README.md create mode 100644 docs/test_plan/api_security_service/access_token_req.json create mode 100644 docs/test_plan/api_security_service/access_token_req_example.json create mode 100644 docs/test_plan/api_security_service/security_notification.json create mode 100644 docs/test_plan/api_security_service/service_security.json create mode 100644 docs/test_plan/common_operations/README.md create mode 100644 docs/testing_with_curl/README.md create mode 100755 docs/testing_with_curl/capif_tls_curls_exposer.sh create mode 100755 docs/testing_with_curl/capif_tls_curls_invoker.sh create mode 100644 docs/testing_with_curl/exposer.key create mode 100644 docs/testing_with_curl/invoker.key create mode 100644 docs/testing_with_postman/CAPIF.postman_collection.json create mode 100644 docs/testing_with_postman/CAPIF.postman_environment.json create mode 100644 docs/testing_with_postman/README.md create mode 100644 docs/testing_with_postman/hello_api.py create mode 100644 docs/testing_with_postman/package.json create mode 100644 docs/testing_with_postman/script.js create mode 100644 docs/testing_with_robot/README.md create mode 100644 helm/README-vault.md create mode 100644 helm/README.md create mode 100644 helm/capif/.helmignore create mode 100644 helm/capif/Chart.yaml create mode 100644 helm/capif/README.md create mode 100644 helm/capif/docker-monitoring.json create mode 100644 helm/capif/kubernetes-dashboard.json create mode 100644 helm/capif/loki-logs.json create mode 100644 helm/capif/templates/_helpers.tpl create mode 100644 helm/capif/templates/access-control-policy.yaml create mode 100644 helm/capif/templates/api-invocation-logs.yaml create mode 100644 helm/capif/templates/api-invoker-management.yaml create mode 100644 helm/capif/templates/api-provider-management.yaml create mode 100644 helm/capif/templates/capif-events-configmap.yaml create mode 100644 helm/capif/templates/capif-events.yaml create mode 100644 helm/capif/templates/capif-invocation-configmap.yaml create mode 100644 helm/capif/templates/capif-invoker-configmap.yaml create mode 100644 helm/capif/templates/capif-logs-configmap.yaml create mode 100644 helm/capif/templates/capif-provider-configmap.yaml create mode 100644 helm/capif/templates/capif-published-configmap.yaml create mode 100644 helm/capif/templates/capif-routing-info.yaml create mode 100644 helm/capif/templates/capif-security-configmap.yaml create mode 100644 helm/capif/templates/capif-security.yaml create mode 100644 helm/capif/templates/capif-service-configmap.yaml create mode 100644 helm/capif/templates/deployment.yaml create mode 100644 helm/capif/templates/fluent-bit-service.yaml create mode 100644 helm/capif/templates/fluentbit-configmap.yaml create mode 100644 helm/capif/templates/fluentbit-deployment.yaml create mode 100644 helm/capif/templates/grafana-configmap.yaml create mode 100644 helm/capif/templates/grafana-deployment.yaml create mode 100644 helm/capif/templates/grafana-ingress-route.yaml create mode 100644 helm/capif/templates/grafana-ingress.yaml create mode 100644 helm/capif/templates/grafana-pvc.yaml create mode 100644 helm/capif/templates/grafana-secrets.yaml create mode 100644 helm/capif/templates/grafana-service.yaml create mode 100644 helm/capif/templates/logs.yaml create mode 100644 helm/capif/templates/loki-deployment.yaml create mode 100644 helm/capif/templates/loki-pvc.yaml create mode 100644 helm/capif/templates/loki-service.yaml create mode 100644 helm/capif/templates/mongo-express.yaml create mode 100644 helm/capif/templates/mongo-pvc.yaml create mode 100644 helm/capif/templates/mongo-register.yaml create mode 100644 helm/capif/templates/mongo.yaml create mode 100644 helm/capif/templates/nginx-ingress-route.yaml create mode 100644 helm/capif/templates/nginx-ssl-ingress-route.yaml create mode 100644 helm/capif/templates/nginx-ssl-route.yaml create mode 100644 helm/capif/templates/nginx-ssl.yaml create mode 100644 helm/capif/templates/nginx.yaml create mode 100644 helm/capif/templates/otel-collector-configmap.yaml create mode 100644 helm/capif/templates/otel-collector-deployment.yaml create mode 100644 helm/capif/templates/otel-collector-service.yaml create mode 100644 helm/capif/templates/prometheus-clusterrole.yaml create mode 100644 helm/capif/templates/prometheus-configmap.yaml create mode 100644 helm/capif/templates/prometheus-deployment.yaml create mode 100644 helm/capif/templates/prometheus-ingress-route.yaml create mode 100644 helm/capif/templates/prometheus-ingress.yaml create mode 100644 helm/capif/templates/prometheus-pvc.yaml create mode 100644 helm/capif/templates/prometheus-service.yaml create mode 100644 helm/capif/templates/published-apis.yaml create mode 100644 helm/capif/templates/redis.yaml create mode 100644 helm/capif/templates/register-configmap.yaml create mode 100644 helm/capif/templates/register.yaml create mode 100644 helm/capif/templates/renderer-configmap.yaml create mode 100644 helm/capif/templates/renderer-deployment.yaml create mode 100644 helm/capif/templates/renderer-service.yaml create mode 100644 helm/capif/templates/service-apis.yaml create mode 100644 helm/capif/values.yaml create mode 100644 helm/helmfile-capif.yaml create mode 100644 helm/vault-job/vault-job.yaml create mode 100644 monitoring/docker-compose.yml create mode 100644 monitoring/fluent_bit/fluent-bit.conf create mode 100644 monitoring/grafana/grafana_config/grafana.ini create mode 100644 monitoring/grafana/grafana_dashboards/Docker-monitoring.json create mode 100644 monitoring/grafana/grafana_dashboards/Loki-Logs.json create mode 100644 monitoring/grafana/grafana_provisioning/grafana-datasources.yaml create mode 100644 monitoring/grafana/grafana_provisioning/grafana-default-provisioning.yaml create mode 100755 monitoring/grafana_config/provisioning/dashboards/default.yaml create mode 100755 monitoring/grafana_config/provisioning/datasources/datasources.yaml create mode 100644 monitoring/otlp_collector/otel-config.yaml create mode 100644 monitoring/prometheus/prometheus.yml create mode 100644 monitoring/tempo/tempo.yaml create mode 100644 prometheus/kustomization.yaml create mode 100644 prometheus/prometheus-claim1-persistentvolumeclaim.yaml create mode 100644 prometheus/prometheus-claim2-persistentvolumeclaim.yaml create mode 100644 prometheus/prometheus-claim3-persistentvolumeclaim.yaml create mode 100644 prometheus/prometheus-claim4-persistentvolumeclaim.yaml create mode 100644 prometheus/prometheus-configmap.yaml create mode 100644 prometheus/prometheus-deployment.yaml create mode 100644 prometheus/prometheus-service.yaml create mode 100644 services/.env create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/.dockerignore create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/.gitignore create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/.travis.yml create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/Dockerfile create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/README.md create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__init__.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__main__.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/consumer_messager.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/__init__.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/aef_profile.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/api_invoker_enrolment_details.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/base_model_.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/communication_type.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/communication_type_any_of.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/custom_operation.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/data_format.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/data_format_any_of.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/interface_description.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/onboarding_information.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/onboarding_notification.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/operation.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/operation_any_of.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/problem_details.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/protocol.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/protocol_any_of.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/published_api_path.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/resource.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/security_method.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/service_api_description.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/shareable_information.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/version.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/models/websock_notif_config.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/typing_utils.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/config.yaml create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/git_push.sh create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/setup.py create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_API_Invoker_Management_API/tox.ini create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/.dockerignore create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/.gitignore create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/.travis.yml create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/Dockerfile create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/README.md create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__init__.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__main__.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/__init__.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/api_provider_enrolment_details.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/api_provider_enrolment_details_patch.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/api_provider_func_role.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/api_provider_func_role_any_of.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/api_provider_function_details.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/base_model_.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/problem_details.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/models/registration_information.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/typing_utils.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/config.yaml create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/git_push.sh create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/setup.py create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_API_Provider_Management_API/tox.ini create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/.gitignore create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/README.md create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/config.yaml create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__init__.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__main__.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/config.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/accesscontrolpolicyapi.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/consumer_messager.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/internal_service_ops.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/publisher.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/resources.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/responses.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/db/db.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/encoder.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/__init__.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/access_control_policy_list.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/api_invoker_policy.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/time_range_list.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/__init__.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/test_default_controller.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/typing_utils.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/util.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/setup.py create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Access_Control_Policy_API/tox.ini create mode 100644 services/TS29222_CAPIF_Auditing_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Auditing_API/.gitignore create mode 100644 services/TS29222_CAPIF_Auditing_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Auditing_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Auditing_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Auditing_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Auditing_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Auditing_API/README.md create mode 100644 services/TS29222_CAPIF_Auditing_API/config.yaml create mode 100644 services/TS29222_CAPIF_Auditing_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/__init__.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/__main__.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/config.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/core/resources.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/core/responses.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/db/db.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/encoder.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/__init__.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/interface_description.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/invocation_log.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/log.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/operation.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/operation_any_of.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/protocol.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/protocol_any_of.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/security_method.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/typing_utils.py create mode 100644 services/TS29222_CAPIF_Auditing_API/logs/util.py create mode 100644 services/TS29222_CAPIF_Auditing_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Auditing_API/setup.py create mode 100644 services/TS29222_CAPIF_Auditing_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Auditing_API/tox.ini create mode 100644 services/TS29222_CAPIF_Discover_Service_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Discover_Service_API/.gitignore create mode 100644 services/TS29222_CAPIF_Discover_Service_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Discover_Service_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Discover_Service_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Discover_Service_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Discover_Service_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Discover_Service_API/README.md create mode 100644 services/TS29222_CAPIF_Discover_Service_API/config.yaml create mode 100644 services/TS29222_CAPIF_Discover_Service_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Discover_Service_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/__init__.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/__main__.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/__init__.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/aef_profile.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/communication_type.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/communication_type_any_of.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/custom_operation.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/data_format.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/data_format_any_of.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/discovered_apis.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/interface_description.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/operation.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/operation_any_of.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/protocol.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/protocol_any_of.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/published_api_path.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/resource.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/security_method.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/service_api_description.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/shareable_information.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/models/version.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/typing_utils.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/setup.py create mode 100644 services/TS29222_CAPIF_Discover_Service_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Discover_Service_API/tox.ini create mode 100644 services/TS29222_CAPIF_Events_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Events_API/.gitignore create mode 100644 services/TS29222_CAPIF_Events_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Events_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Events_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Events_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Events_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Events_API/README.md create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/__init__.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/__main__.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/config.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/auth_manager.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/consumer_messager.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/internal_event_ops.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/resources.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/responses.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/db/db.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/encoder.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/__init__.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/access_control_policy_list.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/access_control_policy_list_ext.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/access_control_policy_list_ext_all_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/aef_profile.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/api_invoker_policy.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/capif_event.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/capif_event_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/capif_event_detail.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/capif_event_filter.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/communication_type.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/communication_type_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/custom_operation.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/data_format.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/data_format_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/event_notification.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/event_subscription.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/interface_description.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/invocation_log.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/ipv4_address_range.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/ipv6_address_range.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/log.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/notification_flag.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/notification_flag_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/notification_method.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/notification_method_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/operation.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/operation_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/partitioning_criteria.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/partitioning_criteria_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/protocol.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/protocol_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/published_api_path.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/reporting_information.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/resource.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/routing_rule.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/security_method.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/service_api_description.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/shareable_information.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/time_range_list.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/topology_hiding.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/version.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/models/websock_notif_config.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/typing_utils.py create mode 100644 services/TS29222_CAPIF_Events_API/capif_events/util.py create mode 100644 services/TS29222_CAPIF_Events_API/config.yaml create mode 100644 services/TS29222_CAPIF_Events_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Events_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Events_API/setup.py create mode 100644 services/TS29222_CAPIF_Events_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Events_API/tox.ini create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/.gitignore create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/README.md create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__init__.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__main__.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/__init__.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/interface_description.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/invocation_log.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/log.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/operation.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/operation_any_of.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/protocol.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/protocol_any_of.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/security_method.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/typing_utils.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/config.yaml create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/setup.py create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Logging_API_Invocation_API/tox.ini create mode 100644 services/TS29222_CAPIF_Publish_Service_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Publish_Service_API/.gitignore create mode 100644 services/TS29222_CAPIF_Publish_Service_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Publish_Service_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Publish_Service_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Publish_Service_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Publish_Service_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Publish_Service_API/README.md create mode 100644 services/TS29222_CAPIF_Publish_Service_API/config.yaml create mode 100644 services/TS29222_CAPIF_Publish_Service_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/__init__.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/__main__.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/internal_service_ops.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/__init__.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/aef_profile.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/communication_type.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/communication_type_any_of.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/custom_operation.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/data_format.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/data_format_any_of.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/interface_description.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/operation.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/operation_any_of.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/protocol.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/protocol_any_of.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/published_api_path.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/resource.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/security_method.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/service_api_description.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/shareable_information.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/models/version.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/typing_utils.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Publish_Service_API/setup.py create mode 100644 services/TS29222_CAPIF_Publish_Service_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Publish_Service_API/tox.ini create mode 100644 services/TS29222_CAPIF_Routing_Info_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Routing_Info_API/.gitignore create mode 100644 services/TS29222_CAPIF_Routing_Info_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Routing_Info_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Routing_Info_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Routing_Info_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Routing_Info_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Routing_Info_API/README.md create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__init__.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__main__.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/__init__.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/aef_profile.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/communication_type.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/communication_type_any_of.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/custom_operation.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/data_format.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/data_format_any_of.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/interface_description.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/ipv4_address_range.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/ipv6_address_range.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/operation.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/operation_any_of.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/protocol.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/protocol_any_of.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/resource.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/routing_info.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/routing_rule.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/security_method.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/version.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/test/__init__.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/test/test_default_controller.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/typing_utils.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Routing_Info_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Routing_Info_API/setup.py create mode 100644 services/TS29222_CAPIF_Routing_Info_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Routing_Info_API/tox.ini create mode 100644 services/TS29222_CAPIF_Security_API/.dockerignore create mode 100644 services/TS29222_CAPIF_Security_API/.gitignore create mode 100644 services/TS29222_CAPIF_Security_API/.openapi-generator-ignore create mode 100644 services/TS29222_CAPIF_Security_API/.openapi-generator/FILES create mode 100644 services/TS29222_CAPIF_Security_API/.openapi-generator/VERSION create mode 100644 services/TS29222_CAPIF_Security_API/.travis.yml create mode 100644 services/TS29222_CAPIF_Security_API/Dockerfile create mode 100644 services/TS29222_CAPIF_Security_API/README.md create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/__init__.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/__main__.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/config.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/controllers/__init__.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/controllers/security_controller_.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/notification.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/resources.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/responses.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/core/validate_user.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/db/db.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/encoder.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/__init__.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/access_token_claims.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/access_token_err.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/access_token_err1.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/access_token_req.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/access_token_req1.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/access_token_rsp.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/base_model_.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/cause.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/cause_any_of.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/interface_description.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/invalid_param.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/invalid_param1.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/nf_type.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/nf_type_any_of.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/plmn_id.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/plmn_id_nid.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/problem_details.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/problem_details1.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/security_information.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/security_method.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/security_method_any_of.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/security_notification.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/service_security.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/snssai.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/models/websock_notif_config.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/openapi/openapi.yaml create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/typing_utils.py create mode 100644 services/TS29222_CAPIF_Security_API/capif_security/util.py create mode 100644 services/TS29222_CAPIF_Security_API/config.yaml create mode 100644 services/TS29222_CAPIF_Security_API/git_push.sh create mode 100644 services/TS29222_CAPIF_Security_API/main.py create mode 100644 services/TS29222_CAPIF_Security_API/requirements.txt create mode 100644 services/TS29222_CAPIF_Security_API/security_prepare.sh create mode 100644 services/TS29222_CAPIF_Security_API/setup.py create mode 100644 services/TS29222_CAPIF_Security_API/test-requirements.txt create mode 100644 services/TS29222_CAPIF_Security_API/tox.ini create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/Dockerfile create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/__init__.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/capif_registration.json create mode 100755 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/credentials.properties create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/demo_values.json create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/events.json create mode 100755 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/invoker_details.json create mode 100755 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/security_info.json create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/service_request_body.json create mode 100755 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/token_request.json create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_delete.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_discover_service.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_auth.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_security_auth.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_previous_register.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_register_to_capif.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_remove_security_context.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_secutiry_context.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_to_service.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/nef_calback_server/__init__.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/nef_calback_server/callback.py create mode 100644 services/capif-client/CAPIFInvokerGUI/invoker_gui/main.py create mode 100755 services/capif-client/CAPIFInvokerGUI/invoker_gui/prepare.sh create mode 100755 services/capif-client/CAPIFInvokerGUI/invoker_gui/requirements.txt create mode 100644 services/capif-client/Dockerfile create mode 100755 services/check_services_are_running.sh create mode 100755 services/clean_capif_docker_services.sh create mode 100644 services/docker-compose-capif.yml create mode 100644 services/docker-compose-register.yml create mode 100644 services/docker-compose-vault.yml create mode 100644 services/docker-compose/docker-compose-capif.yml create mode 100644 services/docker-compose/docker-compose-montoring.yml create mode 100644 services/docker-compose/docker-compose-register.yml create mode 100644 services/docker-compose/docker-compose-vault.yml create mode 100755 services/docker-compose/run.sh create mode 100755 services/docker-compose/stop.sh create mode 100644 services/nginx/Dockerfile create mode 100644 services/nginx/certs/sign_req_body_tmp.json create mode 100644 services/nginx/nginx.conf create mode 100644 services/nginx/nginx_prepare.sh create mode 100644 services/register/.gitignore create mode 100644 services/register/Dockerfile create mode 100644 services/register/config.yaml create mode 100644 services/register/register_prepare.sh create mode 100644 services/register/register_service/__init__.py create mode 100644 services/register/register_service/__main__.py create mode 100644 services/register/register_service/config.py create mode 100644 services/register/register_service/controllers/register_controller.py create mode 100644 services/register/register_service/core/register_operations.py create mode 100644 services/register/register_service/db/db.py create mode 100644 services/register/requirements.txt create mode 100755 services/run.sh create mode 100755 services/runCapifTests.sh create mode 100755 services/stop.sh create mode 100644 services/vault/Dockerfile create mode 100644 services/vault/vault_prepare_certs.sh create mode 100644 tests/features/CAPIF Api Access Control Policy/__init__.robot create mode 100644 tests/features/CAPIF Api Access Control Policy/capif_api_access_control_policy.robot create mode 100644 tests/features/CAPIF Api Auditing Service/__init__.robot create mode 100644 tests/features/CAPIF Api Auditing Service/capif_auditing_api.robot create mode 100644 tests/features/CAPIF Api Discover Service/__init__.robot create mode 100644 tests/features/CAPIF Api Discover Service/capif_api_service_discover.robot create mode 100644 tests/features/CAPIF Api Events/__init__.robot create mode 100644 tests/features/CAPIF Api Events/capif_events_api.robot create mode 100644 tests/features/CAPIF Api Invoker Management/__init__.robot create mode 100644 tests/features/CAPIF Api Invoker Management/capif_api_invoker_managenet.robot create mode 100644 tests/features/CAPIF Api Logging Service/__init__.robot create mode 100644 tests/features/CAPIF Api Logging Service/capif_logging_api.robot create mode 100644 tests/features/CAPIF Api Provider Management/__init__.robot create mode 100644 tests/features/CAPIF Api Provider Management/capif_api_provider_management.robot create mode 100644 tests/features/CAPIF Api Publish Service/__init__.robot create mode 100644 tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot create mode 100644 tests/features/CAPIF Security Api/__init__.robot create mode 100644 tests/features/CAPIF Security Api/capif_security_api.robot create mode 100644 tests/features/__init__.robot create mode 100644 tests/libraries/api_events/bodyRequests.py create mode 100644 tests/libraries/api_invoker_management/bodyRequests.py create mode 100644 tests/libraries/api_logging_service/bodyRequests.py create mode 100644 tests/libraries/api_provider_management/bodyRequests.py create mode 100644 tests/libraries/api_publish_service/bodyRequests.py create mode 100644 tests/libraries/bodyRequests.py create mode 100644 tests/libraries/common/bodyRequests.py create mode 100644 tests/libraries/common/types.json create mode 100644 tests/libraries/environment.py create mode 100644 tests/libraries/helpers.py create mode 100644 tests/libraries/security_api/bodyRequests.py create mode 100644 tests/requirements.txt create mode 100644 tests/resources/api_invoker_management_requests/apiInvokerManagementRequests.robot create mode 100644 tests/resources/common.resource create mode 100644 tests/resources/common/basicRequests.robot create mode 100644 tests/resources/common/httpServer.robot create mode 100644 tests/resources/common/httpServerCtrl.robot create mode 100755 tools/open_api_script/generate_all_capif_apis.sh create mode 100644 tools/robot/Dockerfile create mode 100644 tools/robot/README.md create mode 100644 tools/robot/basicRequirements.txt create mode 100644 tools/robot/basicRobotInstall.sh create mode 100755 tools/robot/doc_entrypoint.sh create mode 100644 tools/robot/entrypoint.sh create mode 100755 tools/robot/featdoc_entrypoint.sh create mode 100755 tools/robot/libdoc_entrypoint.sh create mode 100755 tools/robot/linter_entrypoint.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed021d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +.idea +.git +# Byte-compiled / optimized / DLL files +__pycache__/ +./libraries/__pycache__/*.py[cod] +*.py[cod] +*$py.class +*.DS_Store +*.key +*.csr +*.pem +*.crt +*.zip +*.srl +services/nginx/certs/sign_req_body.json +services/easy_rsa/certs/pki +services/easy_rsa/certs/*EasyRSA* +services/easy_rsa/certs/*.profile +services/easy_rsa/certs/*.csr + + +monitoring/grafana/*grafana_db* +monitoring/prometheus/*prometheus_db +monitoring/prometheus/*.rules +monitoring/tempo/*tempo-data + + + + + + + +!docs/testing_with_curl/exposer.key +!docs/testing_with_curl/invoker.key + + +services/docker-elk/elasticsearch/_state +services/docker-elk/elasticsearch/snapshot_cache +services/docker-elk/elasticsearch/indices +services/docker-elk/elasticsearch/node.lock +services/docker-elk/elasticsearch/nodes + +results + +helm/capif/*.lock +helm/capif/charts \ No newline at end of file diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..ef7f8ff --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,9 @@ +cff-version: 2.1.0 +message: "If you use this software, please cite it as below." +authors: +- family-names: "EVOLVED-5g" + given-names: "EVOLVED-5g" +title: "CAPIF_API_Services" +version: 2.1 +date-released: 2022-01-30 +url: "https://github.com/EVOLVED-5G/CAPIF_API_Services" diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 0000000..14a88ff --- /dev/null +++ b/FAQ.md @@ -0,0 +1,88 @@ +[**[Return To Main]**] + +# FAQ + +### Does the user have to develop the 3 elements of the provider (AEF, AMF and APF)? +No, you only have to make the request to the "/onboarding" endpoint. In it you must specify a CSR for the AEF, APF and AMF and you will receive the certificates for each of them in the response. + +### There is one party that publishes the API and another that exposes it, what is the difference? +There are different services, the APF, intended for publishing the APIs, and the AEF, intended so that the invoker can call it. The APF is what connects to the Capif Core Function to publish the service and when the service is up, you need the AEF service so that invokers can connect to it. + + +### Before publishing an API, do you have to be registered in CAPIF? +Yes, before publishing an API you must register using the POST /register endpoint. + + +### Where is the registration done? +Registration is done in a REST API outside of the CAPIF specification taht we have implemented. + + +### Is the username and password chosen by the user when registering or is it assigned when requesting registration to CAPIF public instance? +When you make the request to the "/endpoint" of register, you will be returned a username and a password determined by CAPIF. + + +### What is a CSR? +A CSR is a Certificate Signing Request. It is a generated data block where the certificate is planned to be installed and contains key information such as public key, organization, and location, and is used to request a certificate from a certificate authority (CA). In CAPIF, 3 CSRs are necessary to register a provider, for AEF, APF and AMF. + + +### When doing the register_provider where can I find the CSRs that are generated? +When using the "register_provider" command, if you add the "debug" option, it shows you a json with the data used to register the provider. There we can find in the body a list of 3 elements corresponding to AEF, APF and AMF. IN each of them, the apiProbPubKey field corresponds to the CSR. + + +### How to use the example client (CAPIF_INVOKER_GUI)? +First you have to make a "./run.sh host:port" indicating the address of the public CAPIF. Once the Docker containers are up, you have to do a "./terminal_to_py_netapp.sh" and then a "python main.py". At this point we will find ourselves in a console with some predefined commands to use the Client. If we press tab twice it will bring up the list of available commands. + + +### Where is the CAPIF public instance located? +The CAPIF public instance can be found at the following URLs: +- capif.mobilesandbox.cloud:37211 (HTTPS) +- capif.mobilesandbox.cloud:37212 (HTTP) + + +### Do you have to publish 3 APIs? one for each instance? +No, you only have to publish a single API but each component is responsible for a specific service, whether publishing or exposing. + + +### Once the API is published, is it always active? Or do you have to republish it every time you want to use it? +It is better to unsubscribe the API every time you exit the application since otherwise it could be republished and it would be double. + + +### Would the same username and password be valid for different invokers? +Yes, a user can have multiple invokers at the same time, and as such, the username and password would be the same. + + +### What is the notfication destination field in the register_invoker request? +This is the callback URL used to notify events. CAPIF has an Event service to subscribe to that notifies actions such as a subscription to an API, a change in the state of an API... + + +### Is the notification_destination a required field in the register_invoker +No, it is not mandatory, but if you do not enter it you will not receive any CAPIF events. For example, the APF may delete the API, you will not be notified that the API is no longer available. + + +### What is the purpose of the "discover_service" function in the invoker client? +The discover_service returns a json with all the services that exist exposed in CAPIF at that moment. + + +### What is the purpose of the "get_security_auth" function in the invoker client? +Sirve para pedir el token o para refrescarlo en caso de que haya caducado. You have to use that token to call the API from the invoker. + + +### What is the purpose of the "register_security_context" function in the invoker client? +To consume the API it is necessary to have a Security Context registered with the data and the authentication method. + + +### Is a user the same as an exposer? +No, a user registers in CAPIF and once done can have the role of invoker, provider or both. + + +### Where can I put my endpoint? +You have to set your endpoint when doing the "publish_service" functionality: + ``` + publish_service capif_ops/config_files/service_api_description_hello.json + ``` + +In the file "service_api_description_hello.json" you configure the service that is going to be exposed and by developing one to suit you, you expose your API. + + + + [Return To Main]: ./README.md#faq-documentation \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7077d0e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Telefónica Innovación Digital, Fogus Innovations & Services P.C. and ETSI. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index c150cd3..27dc1bd 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,176 @@ -# capif +# Common API Framework (CAPIF) + +- [Common API Framework (CAPIF)](#common-api-framework-capif) +- [Repository structure](#repository-structure) +- [CAPIF\_API\_Services](#capif_api_services) + - [How to run CAPIF services in this Repository](#how-to-run-capif-services-in-this-repository) + - [Run All CAPIF Services locally with Docker images](#run-all-capif-services-locally-with-docker-images) + - [Run All CAPIF Services locally with Docker images and deploy monitoring stack](#run-all-capif-services-locally-with-docker-images-and-deploy-monitoring-stack) + - [Run each service using Docker](#run-each-service-using-docker) + - [Run each service using Python](#run-each-service-using-python) +- [How to test CAPIF APIs](#how-to-test-capif-apis) + - [Test Plan Documentation](#test-plan-documentation) + - [Robot Framework](#robot-framework) + - [Using Curl](#using-curl) + - [Using PostMan](#using-postman) +- [Important urls:](#important-urls) + - [Mongo DB Dashboard](#mongo-db-dashboard) +- [FAQ Documentation](#faq-documentation) +- [CAPIF Release 1.0](#capif-release-10) + + +# Repository structure +``` +CAPIF_API_Services +└───docs +│ └───test_plan +│ └───testing_with_postman +└───services +└───tests +└───tools + └───robot + └───open_api_script +``` +* **services**: Services developed following CAPIF API specifications. Also, other complementary services (e.g., NGINX and JWTauth services for the authentication of API consuming entities). +* **tools**: Auxiliary tools. Robot Framework related code and OpenAPI scripts. +* **test**: Tests developed using Robot Framework. +* **docs**: Documents related to the code in the repository. + * images: images used in the repository + * test_plan: test plan descriptions for each API service referring to the test that are executed with the Robot Framework. + * testing_with_postman: auxiliary JSON file needed for the Postman-based examples. -## Getting started +# CAPIF_API_Services +This repository has the python-flask Mockup servers created with openapi-generator related with CAPIF APIS defined here: +[Open API Descriptions of 3GPP 5G APIs] -To make it easy for you to get started with GitLab, here's a list of recommended next steps. +## How to run CAPIF services in this Repository +Capif services are developed under /service/ folder. -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! +### Run All CAPIF Services locally with Docker images +To run using docker and docker compose, version 2.10 or higher, you must ensure you have that tools installed at your machine. Also to simplify the process, we have 3 script to control docker images to deploy, check and cleanup. -## Add your files +To run all CAPIF APIs locally using docker and docker-compose you can execute: +``` +cd services/ -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: +./run.sh +``` +This will build and run all services using docker images, including mongodb and nginx locally and in background, and import ca.crt to nginx. +Nginx deployed by default use **capifcore** hostname, but can add a parameter when run.sh is executed setting a different hostname, for example, ``` -cd existing_repo -git remote add origin https://labs.etsi.org/rep/ocf/capif.git -git branch -M main -git push -uf origin main +./run.sh openshift.evolved-5g.eu ``` -## Integrate with your tools +If you want to check if all CAPIF services are running properly in local machine after execute run.sh, we can use: +``` +./check_services_are_running.sh +``` +This shell script will return 0 if all services are running properly. -- [ ] [Set up project integrations](https://labs.etsi.org/rep/ocf/capif/-/settings/integrations) +When we need to stop CAPIF services, we can use next bash script: +``` +./clean_capif_docker_services.sh +``` -## Collaborate with your team +or also the next script: +``` +./stop.sh +``` -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) +This shell script will remove and clean all CAPIF services started previously with run.sh -## Test and Deploy +### Run All CAPIF Services locally with Docker images and deploy monitoring stack +It is now possible to deploy a monitoring stack for CAPIF with Grafana, Prometheus, FluentBit, Loki, Cadvisor, Tempo and Opentelemetry. -Use the built-in continuous integration in GitLab. +To deploy CAPIF together with the monitoring stack, it is only necessary to execute the following. -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) +``` +./run.sh --m true +``` -*** +After they have been built, the different panels can be consulted in Grafana at the url -# Editing this README +``` +http:<0.0.0.0>:3000 +``` -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. +By default, the monitoring option is set to false. Once up, all data sources and dashboards are automatically provisioned -## Suggestions for a good README -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. +### Run each service using Docker -## Name -Choose a self-explaining name for your project. +Also you can run service by service using docker: +``` +cd +docker build -t capif_security . +docker run -p 8080:8080 capif_security +``` + +### Run each service using Python + +Run using python +``` +cd +pip3 install -r requirements.txt +python3 -m +``` + +# How to test CAPIF APIs +The above APIs can be tested either with "curl" command, POSTMAN tool or running developed tests with Robot Framework. +## Test Plan Documentation + +Complete documentation of tests is here: [Test Plan Directory] +## Robot Framework -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. +In order to ensure modifications over CAPIF services still accomplish the required functionality, Robot Framework test suite must be success. -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. +Test suite implemented accomplish requirements described under test plan at [Test Plan Directory] folder. -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. +Please go to [Testing with Robot Framework] Section -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. +## Using Curl -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. +Please go to [Testing Using Curl] section. -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. +## Using PostMan +You can test the CAPIF flow using the Postman tool. To do this, we have created a collection with some examples of CAPIF requests with everything necessary to carry them out. + +For more information on how to test the APIs with POSTMAN, follow this [Document](docs/testing_with_postman/README.md). +Also you have here the [POSTMAN Collection](docs/testing_with_postman/CAPIF.postman_collection.json) + +# Important urls: + +## Mongo DB Dashboard +``` +http://0.0.0.0:8082/ (if accessed from localhost) + +or + +http://:8082/ (if accessed from another host) +``` +# FAQ Documentation -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. +Frequently asked questions can be found here: [FAQ Directory] -## Contributing -State if you are open to contributions and what your requirements are for accepting them. +# CAPIF Release 1.0 -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. +The APIs included in release 1.0 are: +- JWT Authentication APIs +- CAPIF Invoker Management API +- CAPIF Publish API +- CAPIF Discover API +- CAPIF Security API +- CAPIF Events API +- CAPIF Provider Management API -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. +Testing Suite of all services. -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. -## License -For open source projects, say how it is licensed. -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +[Open API Descriptions of 3GPP 5G APIs]: https://forge.3gpp.org/rep/all/5G_APIs "Open API Descriptions of 3GPP 5G APIs" +[Test Plan Directory]: ./docs/test_plan/README.md "Test Plan Directory" +[Testing Using Curl]: ./docs/testing_with_curl/README.md "Testing Using Curl" +[Testing with Robot Framework]: ./docs/testing_with_robot/README.md "Testing with Robot Framework" +[FAQ Directory]: ./FAQ.md "FAQ directory" \ No newline at end of file diff --git a/cicd/exclusions b/cicd/exclusions new file mode 100644 index 0000000..84a40a8 --- /dev/null +++ b/cicd/exclusions @@ -0,0 +1,5 @@ +../helm/capif/README.md +../helm/capif/values.yaml +../services/docker-compose-capif.yml +../docs/ +../monitoring/ \ No newline at end of file diff --git a/cicd/ruff.toml b/cicd/ruff.toml new file mode 100644 index 0000000..bff59ea --- /dev/null +++ b/cicd/ruff.toml @@ -0,0 +1,3 @@ +line-length = 120 +target-version = "py39" +select = ["E", "W"] \ No newline at end of file diff --git a/docs/images/flows/01 - Register del AEF.png b/docs/images/flows/01 - Register del AEF.png new file mode 100644 index 0000000000000000000000000000000000000000..f1454c8bffe50c74247e2ddbd9e3ae4a4da77579 GIT binary patch literal 71533 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 yD!6Y;)dE5Xy$L_Eub9e;G+OD0;Hd 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

(`#R2 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 EA6LK9@c;k- literal 0 HcmV?d00001 diff --git a/docs/images/flows/02 - AEF API Provider registration.png b/docs/images/flows/02 - AEF API Provider registration.png new file mode 100644 index 0000000000000000000000000000000000000000..3b42e21185ae36c97f3c6504624757a80e282ef6 GIT binary patch literal 49215 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 mWiR6Y|L1M)|L-L4fYppywbA9Gtg-NFa} literal 0 HcmV?d00001 diff --git a/docs/images/flows/03 - AEF Publish.png b/docs/images/flows/03 - AEF Publish.png new file mode 100644 index 0000000000000000000000000000000000000000..dfe3a3e09ff3183fa93eab95e1df107a2dfa9638 GIT binary patch literal 43268 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

;+2huQDFFW8~?y}*!p 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

Ti(31Oz7P%yeFy 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 literal 0 HcmV?d00001 diff --git a/docs/images/flows/08 - Invoker Get Token.png b/docs/images/flows/08 - Invoker Get Token.png new file mode 100644 index 0000000000000000000000000000000000000000..2e39f52a3d12efa8c19ea3032957e9f48d890d0e GIT binary patch literal 55546 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 CaPF-D literal 0 HcmV?d00001 diff --git a/docs/images/flows/09 - Invoker Send Request to AEF Service API.png b/docs/images/flows/09 - Invoker Send Request to AEF Service API.png new file mode 100644 index 0000000000000000000000000000000000000000..1e4a87c54b04d2d6524da2617fa615dab7318dc7 GIT binary patch literal 26214 zcmcG$by$^aw>SELNJxl)NQ;7sfOLa^(ka~_4HD8RjexX(G=iie-O?o>A}QTSH%JIl zXRzM=?!CWne}8<}bj83|G3;_|N#^&evpgc^|&eWK!;vhm(cm{8*OA2XLSUMa~IO8h7I ziZ`B^i-~1tDD9_LT8JsiX`M|LR$zTQVjwvD#vY{;vunaYuW5Wva|Y>tL?3rKM%##ra9kd;Y4L-O|$1_xvuV z#>Tch6t`~0d!7BQKN!~LnYIWyZoMv~Q|tVQkB?74U~*?ILoD>#HCRuch`r;}ms2&K zJIxq)cz6Y|ukv{u~9#kxgXtII^9RaeTB|VmB|I ztMc7-sI_%|!lsc^)^Ka$vDc|9(sb*&M}L*g%y21|Y#s$g$2|h6Mz6E>aPkh*GVOvO zCAsDO)t@!Q6ciLm246+<3kpz>s+Ut1PF=T{blytRx>vBiocyBp!*KAEBI0w~`!s6T zVtcy&z&>7*R=rT?g&2mGJp4R@U}0f(N9bQ$A1?6cWU&~etCtC^Kzm3}Z?Rz^EbL=I zY;9Yc-hFg*q*gA)Sz@oFtIN*LuALXeWwwD&MC1s6?7H9)H4TkXe}-7heL0K3sKe}r z2CvC4b~kU{L_tAO{wRM>ij9@kt~d3us;a8>MkieMjQe^)baZr@_j&b)5Bh6^xrvF1 z)*B+VW!@KFuD0;sNl9c33=H*{w>|g!KRoew6vv|f*ii3tq}ao=Cr9WzVQ)YN>zk(8_ak&A=F<6ubL*VmWjcaB^#0U==!9wndk zc=@kizcweTmY0^KX`@}H-ORqdy%TmE7Z=B*Q7oLTgiFq41(%KZgoK35cwaoGp%Gyu z#z03G7Z)$pU|eZ$3BZ2#p3iBy=RL2(5*ixXN}{xsl-u9^hY|B;Jt;Rr+Yp}@KXW{H z+ipF4_>cuP(}cz(>rs4cY+HN#bffpo(9l7DrUY}r4<8>NyZLq$q^`ccwY9aZwDfyd zm$j8uSgoRx(r?&4k6m|~hK6D@KBc5k{5`%JVKY+n+{Vld0~xJz+pBh17LTODb$IdP zzL+9>tQyx{LpeFQcqZLx?~AiS-P)csp~kE%G-PMWWyX4@;XU;mp^H=Hk>mEe39ce{ z?%lfw7bief1hSHO;B0I3TyFV|Cv*cdaPdNK)s8J;K65M`sQT`r^fl*x1;x$K{8VP8Q%o^aA`%_(_}%${B}Y8d&fXpsp%C&qove0nx94$K zl6{;EJNk2e{{F$iRRj$KV`O+(i6}NM&eX=HDB1RCXO2Gh+Wom*R~B2ip1_{x4IZR= z-JPARb>j&p^CnqzYvUD`#X2=4-le0ZCfEYm+7?bu6?WW(I@N|N= zTHDR%HixZc#I@K`*x}~;#w#f+AEcTD;*c5&)Do-7>*-N(xNc8B4#^GTiXB!D(yMo; zgbz26Ez{G}gZR|H`lCeTw9VH*K$=ZC@AIbhsI~Lkw=bS2Twy!&kwQ6HStLEdB;ub63OHd2Nd;V4@>^?Nwo#EI4?z|0 zDXrhXf0O06o*wUo>zu8AOw;<~yk42zu2m|XJ)nva@DydU?szHr)t{}i&8itcKRcz z^)@qth>z@je4hQJ01P{(WL%;;o6QqM8~$9-h%Ji|yZCPY$hDggi<)qxLT!jtCMl z|3E(F!|i@@27N`v8^{NnnTCDa5l6DJ)$Q#xsIX~iHa0ff+uOIv$o@j9UKJEdmRD0F zW|<2dpb&6X$Qz2L<#pcB*vYv6XM0A-^ash5xx;b~E;e@Nv$=QDM(U)`y{Z=eW4q`% z@1!2Ck3@QXX|fYwVX-|}8)EJ*%#DqSjlG(udq1W?t76Unx*!Y3kid^mcqD(^+6kBKnR6#ser(~j+?>)fFA+D`VEkGYZ#S#Y|h-^wYooohk4 zf-alDl3rQq4DGr#5Z8Y${N~QbG_R1*P=7*sxi-n{sRqxJ^`b_2J{-zZFVd^8aobx8 z3&UyUeHV{vGbv+3hr6L`UwsOo#&I^7@Bz`at3j>lBA0vkaKeT=E_XMN<5A-jetTU0 zEs1mm1i`V1iPF|jhzgF~1AG!r#`zsePFI&q(a#Ee_Rs!QXD5ID?CgB&?M>sfBzC=1 zRajVv_&|r@({gs^LYmsz#JD%1m-Cu@e>XTd$lP#b2-ofS8jhozyZgXiJ$>xwnwoJU zvzOC#n##(VCuEFw?;67AzdRzN0$s(7k++4o+EB=zJ?nk*=1q4p_p=lpyNOC`=)$(e z;~FUSb#({=T|At0!ItM*fL{qWm#H#Se9%9S_;>GgY8+n-=WCjnn4J9ChHD&_(N5Mw zBebE*s;fJNDv9<4UeE947N7~mCr_H8%}={6Q_gE9%dbzrgjK*`WImPR#^Jul|C8aP zcGXK;w86FVRcVW(>52~@kk(>YLsVqi>%^L(BDw?#1k#?6&7CjfjX;o5En)M5)tE+=WOw?e9eZy|ngNFP_WXF&% z=2mN3A1RvW@dETU<8`t**BZp{vL!1oKg@acBTM1)Mm*$;%XaG4P`ec$KYt_{=h|?A zHd`XBdIsR4S+Ob?M@KZo*u+GU=<4nF`+cGMzid$l6H0tGq?OG_g|!$3Sr3-?;idix)e>`U~~ zF)_7H>*x}ZfP$Nwn^|;h+P7e#&@TAJ-X$kvv*Ti6rC*sNBS4U|thL3(d+}Yk);$TV zSCFRVJ$5!Wx{v|gM=~FEE3FbAb}^(6ulUaM=&TGUEXK#(5X6tBU0qrdzxb4NB(9vU zfOhpN3PM3idHb=u@z-!H!uuqA&z4J_H?f*I;VQR_>&*8(}jFy0i1pH^W|1r}Pqrw!!{lvo2VWnK7>%-pnzu>U6i^ zXgvRGNfOj%*i6o<--OJMaTeL*gwAMOx27+sj{cjyCakCe*c^IH)ypB=)5ZAbH7?sd zre&KO8#(gt|1NYA{*5l|4h#$w^!$q;HO`yYW-Qw~I<8ajD9{nXN7~$c?0tTEdg`G( z_#{^aekYQGcVK!twaqYCGy}Gk_MfQ-nXmwgO!3~QyB&rl8r1l&0|Q%BHST}DBBm%N zCT81E@VwD$=a9WdQCIh|^*Bd~hLwp4C%}1cZ|^A`75bs*dospsq>&xue2#P~6k3!d z*7xt<2k_c7G7{gr49zi;lAnv2`MUT^bMqsBaB%Ie0(uGxZw(%j(2!K8a{!z#wgKiN z$6c3`gD(H5IUcnj1FyiT)`=C?2$oq`vt(k)|Wjv!eCe1@*byn z`nI{V?X>5gDH@50)1&#wovAyh{aPQqZE60K-u1;?MfKH352wV(L}Qoy|M^+&WE^)g zS1r?DEpN!8Vkg>7z>0e|ZjUEoo=1Mg$3SD<%MNqbLf^MOGr;-_)*2#HsFb_5PQFE~ zvh?_KZk~Dzz0bkG=~E3_lE5g&ADYr%`0bB9sM30ucU^Uu;%TKc8aFqoTl|WDO!v2N zO>#IX_xdwGu)hXymF-cv*a zpLmi#X(llF10Gp;PD4X_R7>OccOxa&pXY_IsA3AqV`04DiO8J0;@95tN@8!^_UGW- z%O}|;#M6`CRQ&*&K#*4NesEe`Uyd;QF@C^K9*DsZ{wC_h`0Hk_O%Dd>KrXJ(G?T0A&7u&5yG z;i{-o#*|4H*^kJnoV))CR#4TF{oeMI=y zQWC3_au%&C-o!b6St$MeFD%H#*FYmkc(T@q=9qoUcjXO7E-sA|s0Kf%|9R%H_QoKz zbDE9BwM&0yNj_*Nv6W0igEam4Bfw*2xSZQkDjkqmDop*uH~bAHW`!53OymU>lf|w0TstZok z)xx#MEsTZK9sAa6QCeeLT-mUQU%KD5B%B^cMHjr zKb*^d-y9oimT&RapnoR$P|ZkyqQfj=OPXM?8T;z>E>5)20>y`c=#n0jZ7-^Od#BuA zGW^0hjOUZ89;!HaSS7=T{dr8llDIRwoQ&tsXGKnP*6f?PM>|4#XyQ}f9}0P|^NQo^ zJmt)a)HO>iu9Q#IR*8*P#lqZLHmZq!?cCeB&+U=I&#!q~FzwGyVq9BAi(T0uI;sI; z(*4ohosWZqE+izh*4-WLz+U>5N^?c&J&lFN#&^i1WUUL|BFZ!K$Qx(~NoT)p!N%P7 z`j92}^|YG1u?N&{PZ6Z~*PD&nVz;|EHr={ce~jLqWeILu!urbQs}VTo>izrygW!V& zTo=9`ZQq`>wv?|LIs}f_+%mOI7Wckn22l8lYCh-n8YQnJ$eTASba9BzPa*v}|CXgQ z!9egtKC7MT8-b+pY+ESlHFGJQ5|5h;`JC>a$1ZgZclcdoiA@zIE6ePVOm>TB3bEdNIBm4HY0WC$<)*7 zeXYi2KKZx0l&spps%~Pc--nVrs=Qn0-(I9N5_qp<#ebZb?7bgJKE}PMW$M0bl%n5A z7wCSRZ$MR8N$T=Dr$@6j&Q&Xlb4Hf(KJhM>)z~Z6a7fJID>;OJ|}8?;p#{h7_~6*|-RFn-i|?9!C%n789<|L_T$ta0V*%9DyL zI$VSZ(O$Dfh?jA2ofWhoTf)_sU!19 zZv~>&V<0@vhweu^3W%`QUrIkq>-9C}x8Hut#3INum-w2`N_ZDDZtu6I1W*u%TV8qh ztvBA+#OUNP_1r~#3c?*HS8mi)@43xr8Ts~768!|f)bmDn+(gXVbT-{NXDsO@bV{cayE zSZ2z$KQ>HhYe!sv*XdQ9*pDw1tC300t$2L@D8WXAw zZzr4KBGh(|klBsn(5}YF`5jTDwSw%X{9Cd~3)>5j*E=hIm6@m!m~r)zwc72|6ZLZ` z5OFq*+(4+y30|W$N(BYsxjPIMb*P4Dg$%TG2AsA$sM;Rc6;0LLpzM&v)-mbxX>x(w2;Yp7$xl zy%A^#g`iuo%_imukJ}d)^w}BCU+*bI5ubs92Q{R!$F8OufoXsDw^$#ze~UA^u0e4= z&vp;_kgPtk>|{kX5lCH4RCo`oMVi`Y?+#Df=;JCQqkaW6Q=ze%N; zvqZNoDUx;93}Nf=^I{ynn|h_z{Ogoo80unher?}yIJG2?uY{u3=nG8ZiSIdOy32wW zJ<^6eJ%+8FU20#$n2#^cGC!&1DL&+|2&gPExPFzzr$mzJ`GW1n{!K*q!L0`&8Rzn{ z%b^=Kiz?<1zkduG`80=u`@5sEZd}pE=_-;UCwr$_?Q3X}KRi|Dni{3t$tQ&n-ZYRC@V6ng*t+tpp~b1VR^MxlQzElW{KOd zRVruaO#(*wyrMDIuF>@5yq&#%Dz3Z4$ZTk0ztObkVcW&y)};aLy7NB_x+LgGAR(;; z_3^TO&$2R@EsJXf-_Zw}rL+{EZSXlB`}a4`JUY`U7%tX8LuS36^hbDp%%^x&Hi~NQ z|DgQYce)dYi`-zNR^ndQ<;<&%Q{JDBc(;m}%|yegSoQbcpg4|a<*mMxZ&;!ORPy>< zkPGqIyQM64n0olq#x|gmtm5t?b*igPea)UDU(XAE1uBaYc`D^UBgi zN{D7V9tA=C*l!*y0z}`;^5zlmqmRm04M{sI?(+I=KCmA-B};R;xFe>xcvJNi9&K27YHz81N$IMreZlNJmIQT4 z<)6{=ZLOvH69J~>ldIdIuQP-qKX&UJ%?y&Sa#kE53dh$&xGwBgR)o~`vr9(>{Mugn z(~DD^qv^yI1)(9f$A2F)1Ya2w0XFar=I)E?l$g-n*OntvM%# zx%0;0yIZP)oy~~pW}mA0dLUtb&F6vNzkawM6Z(GDT-#{9#f#u5a}Ev)Fh>h@7sUwm zTd1Igb`y?;ZV2ROF}+jUt6PviC_`q?K3uz^pOdD2+X40gXOqrW5^#eJ#VDX&${O-oCQjEqc9PFA5`w69)q z(7=4NS}&5PD)hw;^MPb=eo$W}d-E?u_@M|E~Tnjr_qyEo+u_YyJxL?mQPuSe6aOfxRzy=`ljv1 z&g(T9r8z0l|$i5J_lH@;-gT$1G6EC20Tgs@4kZ#se+ zzdK9Hn&dxz%RhG|go#X$n(wZhb*r2L#+Nh8J>B({)7rU51ej=7C^KC+N^rTYH=5?_ z+Kq6nuY|VU#YF9}oBXjpaf31nua7@zG%#6#ilW1WAe6arOg}f(j)wv`rC~|mB<<5k zynge( zf<;@F_xeXs(k1f#M8t6)#Z}Ga@g~&L%)+soj4>RB?RV2vEU@d8~XY^C1Hjj(e_^>=(Ka5a&vGd5P zwR`L?)-Wndi$D2A27c0~-DzxM-Fs7%cy+DoS=AFEF2K~+|A8DNz#^9Re7%$RN+zZ_^{p}AvqeDBqt+d!I6=X`N{v1 z;K8$03SN6-c>mw&l!?3!IaO7EVj0vMKuxTd$<58Zf{p`1mu`*YrDcfoqo)TX(6im*nmbnjK}Nri+Col$I;GZ9w0gzbrW35 z){YL0b4P7W%?jV;NUF!*J3C3)j4|h5VEh8n80>|^y}h5eQUcp zUh(D)=Jo55J3Bk9M(tl}YEmD+I^1r&hzJY&(b);-IgnK%jKprGFCDaYCarS1`}cEd zYLY5tM^xS1+$Q2GM4mX|U%Jhpi|;M>R%OV=N?%1lD(4WGDl@wtXaIQtv?pKN+WPxH zfBtM`Wkvi*tK4B(UNG&M&4GxbiiycRPXX7R*#PWYY^EwIDrm?N7$WWmYxjt*2^}vG zhKtY7%{9A9G@SmHL40?3OhT|?k z)!W;<4R#@m06#xJ2gkdvML3+0EKwpFs&%m$4|?~GXv$Ep&h-Yev%jjG;N0Yc(iQip z)@|=T@&Wt>bmz@+Cs@)jR!*{T5YN&@f^fFq=;@Nijra8q3@ELTcs6P976kB;c_=?w z+qoFJBPf{KZCa#V)${$kbgs%;dkVLW9^5(t0sHW{vSUsM^N%tT2Hjk z@BW&fH=yD7KKIbn9D}ID%KYS{4&qZ(v<>&{{A9ZkV*T zJrCAY&1YI$MYwbHqGF{N!4T_x&mSKb$7R+-0qawsmZv~BIW+~o!KG2SzoHl=31wGB zQSk}>SMXB1zJFJtkA2As|Az1Y7?WyH&XtvEVx_^^Y&7b?%TEfsU0wY|=M z@tRaL?B){L`wn(?nx)2A^~-*Gx~s8C{m(?4^z&2VIr(7K`p|xS#?vY|1oH)UDh1>d z;-7o1&d+DwasYErhe++4jvkA}F6cd9t6qva&+T zZmK{ehW|BNCY~g3Yh$bo?aAo)_~F`+B^Z`OVrTn5pFun+hsNV@%xrFME{qlS_xJf- zFE9td7`nWrv{GOLrIr-#e{Wg&n9j$dhG+CJ$@ku;R?Ei>SXkKDG?;g(she6`jo{;l zi~0Wyhx;cZCr8O<{4J5)4DuFWVp+P2TXB(7!8@y|s**;^+MFz}ub=G9iL_$gV%BqX za>}l{`IDcseD>EbHrv@Iup?2BL$F}&eu*llKs7r&ILMYeJ~=TnGh=TL3k@Y~n1wWh zR)KS8^gSjfCOA*Q5fSLf;Ls2_ciGw5ybYHQH~dLmy9_&OkiQ9@VmSe7H)#F2ZikjOiK3QSUpYI{hyMHbz~njrSNavxtF^7Bbb72lC zU`zMCw;$m*DQAKG1}T?2^z@%UeKLncRSu7o;=95s_m4HKU~_o>m6L<>S7|jyKu%r@ zjvW|skUhB;@D%aUD!{|SIzIa|vs&KHEjV8Ps!E3m+Q>CTf40f@&Ye39>V*{SreRyB z8DJVnXNR#~?4?~mN$X?P)zyW7PuR#!M(oTqTwGlDD7oAeJX|t=-x8JlpJS0g2`~f6dfJ8~T ztVZEAS30ig-qvq$mrda*$;mN=jkvnHT2fL1X9UVe<-_c~-CZeJSpoY6$)``By1Me< zq_7yEM$E(e%gM^h%E`gjUQOb(+$UHgW)~1R?TmQTLjj`js<$0(&85!<>wl?SI z*&UXCEG#Uvh29eKIAURAi)J;QY4C)20Yo+C!Agg{b+$9tT4vg9n9uN7cDKwe7CIQ8 z$#)`+8a!eC9yg9)E?2YkE=UEwI^5_qErVhVpyPCvO9tbZ%`VCxhUvOzKpNfbu>(xn~ZRclAhfchH{o2O|5lowb(286# zS925mJQR}K4H5#jvp!J?aJI-eE#67ef{#4`poTn;p|zCcZ|9Nt&tm(qD|#NcmLc}j z;Jld>l@Q0maIBT*Z;~;hM@lN_@#UrVAU~%eoL?+hMGG+-ehPP|q4vJU?<9d(Xnv60 z0`vHtSMTT0dmOI&#{IjW^73jOR|y{LjPP?l6%%WNZcO${dzVk&T{n?DBm*38$fr== zyt%lwb>4B?yD2JP%y%$-zIk~MT(6DIP10xK#eh`I%$6HGPm;!-bhYi*Sg>1ISX{%# zHtS7&6w?Vwg}njwDQhh8in&{sT98k;1u;W@r?sy~zi<1l;OA?Uw0u+LN|sZ6mzFlu z% z{eyx!N=>@PC$P~n5;>eU`b;BO2bu@dq0-qtraE3VWjM{Edob$ zQ;1F89~K;Z-0OXAl<3_j z3|?IML$oJvX-NTs5E2@F$MfIBRKh^Z*qpWHft?@|$N0j^j3pEmh-tsGfX7i^#;_qN zMnSA7^>_pxEiQ6NSj}sSTny{pQ&B~ODVqE=df~dzDU0D(%xaxN75a4XS)OSo zRD6)QRk;B2Ht*sS^KI)J#~Y*lx*6ED2%Y;y zcM@l3XD4t0`|7&NO0`^-mXBdv&h1Z!o@DlyS7Bp{p5T*^xI*NqHRw77LaSlJCog_;d3`Nba1v(6doz+UJ3CAGKweZ-6may~ z%b1BcRA0CO#R{{Szuvn{qafv>!te><&>+I_GLQqEkfFXzLlfgZ!Y2s~2nsS{)-M|a zxBSfrrLHdtK#u<)^3k;2^!S%9dRNQ0pt{DBty(x`OyJ^Pdcrym)`HI%9qX^4?z%_E z$D1v*#sNM800urku-6^sPE)5Gnp_b(JJvvhwzjqcLu-KZd1?g~Hod{oy6=rLY_F6_;l4;Ol)qnkeO;^D1-LlUe) z%X;fTky471G400>S)5kLR}S>`f#a^FmGm$dDC*;(uk*XpuJhrLn{ufA9I8Tp6@f;R zt3n?osjn|C-p)Pa;Q-YXA~EHLdX6_aAI2)>5{0%A1ZPu+$s_2bFONe>SXKYxG79c$|8 z=_xB4x%cBxzEnzIQTsGO0X;h4=^aY5u~HLILFkAeEO-6|=XgQD(Ml{wnCg?iyqtoZQZ0}Ynu9X4UaHnOYT{4^ditj-DR*yrJQtAzprd332gM0Fdy45X=q<4mOa*W48wiQDHFzq}9>$ zXsdP`lBAGFGUsr1b_Qy`BY3bews*PDA3eH?EG#Xx_yc)`ly-Av#&Tt$9FG>@Ne(eZ zs1%Tdci*o6Ll?qUZ|;uAU7^6jyb>&)>3gRup7}PvGowI6WMoxEMZN9ZQ+M~jP`V+A zYa&ey6&zwqfy98VB=En2HnDmMIBjihN%);N07F4Whxo>gW^+P!Xy^_QIG?I@nHU{y z8slkQxKGBx7;1p2`v?f$WkBAO{{P6$G}baQG9ZD28PEa%qkW4qY;|tVV3a^UO%Qq$ ztT?P}S+8JdXlSj+F|3Cjgj639E`6BK74h;C6rcnZ!0#%y^TsGjEdwndpF5}|`;gmy zNKt%~nD{c_cR%J~thDPx4i1j{_XAmZf2;sv3ygs9xLvhQtaNO2G;jrBNcsUP1LS`L zO;JHXnEUMSUw5RbK)Z^}L3`xB3I;?vDewXfo~G|WktPyL)Z=&@l&nQ3eqTO?2WYG- z@IGmPz*B+d(!>D)0VILVKW!S%AiPghgPTXk#Wmd1Q`pczB@Rkqc;>e4t$sKGHu^xxC^;IJuRWIM|YT+BWb0ob*5L& zKG20^AP7L#NXYL>OIuuVT5)|w{9iQbe`7NLN3vsVd^rK&`S~p?Z(SCDVUF8;I5&bo zwieKyi|aoRfR#`T0e8d6l5?40c?ueamezPUIXA?VA3Lt}LE-!vnzL-HjBWA_;3IJ3 zi_QmWO+SGU5EBuBAaps!ASESr-*j$mjSL1gc4nU-O%OqZy69B)?Z=PTMO$+Z0}aB* z0AdM?ilRwH-;JUJ@(ZUYtW%D|T!XmvZTq)>NL<^l_p9*6MsEmv3IKoooov&^yYla6xomS z;gtI;fGWks14ZwqJ897pK;;PlfEy5CKqCI^)DbS0fgw~Lv*SfrXZSJ+1%(HEXo*Ow zgRLokT3Xu2kIx|E3Bq7sc&lLv3y$S9p1M{+WqP_Vt<=v@Q|b2!TTOuKxNN53Ml1l+ z8@~rS9Owja+C4m!myyZLI|IpNzos3Ad}d+3O-pl68 z34p~#Cs2E^qtJJ*eQJG;MQBR_wav=V(9ptS4bJUIz9x{Jn1qB&Yy_?RZ<;j}Y#5?w zPT_Tkpx|YLXe`e}Z^EQ&1Sn~6GpM*OW9nUtEu1@nYkhDVDfyiz>)c|tjM^X4(S3t? z0pNTf;sKh5LSXLRFPlrK?BT=1$LF=*FJS{CTFi~7s3K~BpaC3%d;~QH=+)8jabiLM zGvdt4y(|H*4*B)?cMjO z_L+2Rz#1XL4XIZyY>}!Lj_OAMt>JQJzSv#SV=FNayzEJV`H*&pQJ;VgTU%P9YX(Ej zq)vooqvbCMgIaU*^Iw0gQGJ(~$ZPx!KV8Ax#^wTYtz_fCZylYT&w+0_;-3F$yl`@M zhLaT7`P^a$M1(*S14c?w8@1?+Patfdp`$~(b!!Wlkn@^%vWbB~x&~ulSv7OP?WwpO zC=M=bgR9xxSIal^X~i`c1Q`|=7cc#j)d|ZM;GQtH;qZH*^U!&rVirCRXmGBpEQGDa zt3N-sMnRVNUnc0%NwR5>cd2j!*7N5xpjQh5ovo*IJ5bCU0!0o+fvjyL_Mfcz=$pb> z0JUrV=f~c+cSOb~;?)yD3w$G*(bCca+^MpP`R|7ZK$cp4QW^0vUyJzw3KwSi88z5^ zR7kR!@P0R;prRY6{AYWtkL&wY$u)fs^)Tljg-(?04MNi7>Zre*a)5P3>9UTq)($)U zI69}Z*1>u+l8BdsS5s@qvXyOM?C=g+T+55;FJHb44yxR~eY-^CvXhxl+7{up%JF!C z-ip(@Vr@j`fWu^GAZU+{nWcA1#BEb%yOnT+^56q`xz|tR#O1SW0yVc8&QrQDwDs&wQGROt|`%fB9;{D>x z3Li?Rd92BjQ57E;)vY+&!2C2Fzr*hDvr^licW7QYaa?J)HYK@SmTQ@mXc^rrO|^|H zDC%K}aKT&SY&6>6I3@_;N5~w0d^@KLbH;zemDw6exzA$aKqR8|MK^>hY~lyUQbN?3 zBFQFjwf4Lmyd0|t!#BaNoFHEx1v%_)@35vX-Lggzq+_=O`teZvP3tVySYS*KSm38m zpP+QeCv$awRq+tKfGG&Fa8sy2>FMb}@G54c} z@jIK_TGVEo|I6nL8VIi+qLwY2Y~dtH zkiVmVplY!OIErGHuQm6c0&RArMMFgiYBea)u1)FHuZ5`*1mwxCBEkWdJMA1au}jE|}3;sg=^PlQ9YPLyPpS{^nwHuP3_`{ZQpe_c5k95u~9 zi&!)niH}kJsP%rjVQAdoiHM=a`m+$o&T4Bs^siT^Bl_(sP}3}O$HyP@+xkflD&%oU zp5VjC6=jBGv@zt}xoYp#iqYUxUImMKbavvmSnA^EE4T$o)|H|-zUD5B>CM_J7IbK+ z{agQcR^or9iU0lcu8+V3NaJ(*41*_7u5oan7`~nx8ykc6rNcA=Ga%ohXdF*L=DCW2 z0fx$FR(}A{4Gj(On_wt@fATu1Izw1Td z!*IetD@2msVS%A57Qi^!oiOs# zGrueNcZG&el$JnDLIQL+qEvdK5SJOxk(rqb(AGHoPu^5s$!)dlfP;BDxLu&`2q97Xx>K0v6N(BZe@4G7ONj&wG=fPm)rP8IMZf3%ofL z$7bcJaI7H80+2;}l%1f1%|jVD2`gMyf~%2$3q6RL*|lSho&pHrt~6a;<`vv%bM+{DXZei{um zAUOcVhtQ0tCMN+(BgpXZFiejg?(TvGy#({>5x0fTp`U*HCW#0G*Z}EEJo5$E+4=cI z*8+Ba8sl?wSAi(mlf;<^6qr91H}PlC#KtUVtiaaRp1zy7?D`N4TnJr6gUiwAV7hY^otAu_v-q;(uG)D z!L{H8=|NIf7G?oKAjPDFAp;m6D*>bk8x`ir>q{NqW!%9JWZ^pE%E=Ve92_3rf?W+C z2;{t+oSgcpC)9dR_!9Ug8@(@O95^=c08=kknkFiq`T4Y(*B$(Vuq~Zuulkz@?+6K9 zG+vw)1xKmpYZ$1R;bZQx0v!XUa(IybFVPilg&YMxqjqI}H-!kb)-6BkaxLqVzkUDG zUX^oXQF6NZ0cnVKT}SK#zla=)8O*aiLYl_MYoKhVr^7fDL~G%vu;06w&sE*T ze}i`|zH18H9I#hl(#+DrV!__c+PXj~_w_SU>y5C0&zGCo<`({&!#gZ2J5Y~-SM+pu zd;X)z_JVZE_@^_YUKf&{;jntZN5Wy&3iQq1-bg%~c?leBRSb@KAJ=XyJUl^IKT*-w zaCE`qp`8AIq05E>`+-POeG|+^{sJe3`O%{@n1F(w_XPj4*S%2ly%fN7DAuO%_S={ z%1J7h1#q!w@20E!UaNrX&tJMMyv@M>F20UW=Opt1)z439oXokilpab&KTTJlk8L@eYB%j(@Zp7F@t>drJ%0R{w8;5`UpWQL0bRHd z=C(3mPraK%p%?`VbEvypjy|@%tt~qz=kL+co3>w&m1&`cs6~D?)wl=0=NkAf`7Ei0Sx=<$>CvVaG#)~ zM1+T%l#Rjc@KE=s!or@hFv*Kc=2KtWOoz<6hU~91Wr{u1Z8~s4`EQ;hm^Ex z@B0-b0W=JNwjg?tf4bscTFf}heg69CorwAUJgX9od=+{KUuh~R%+AkWPD2A?LqWg_ zLq$c^`cvk!FTPX>^y*=1qTO1TZYTkEi(-_C;+c^0 zF*Y|hx3~Wdcn2pFE1(7Zye#-46?AkcFV0ZFKp`3mhnP$$6fM}#fOZMd`eDu+X@X7$ z@&icnOR%0Ww>xzNs{aEid&rpl$F==n>oEPdE|T2#Yjd;Se(^he3CyL_>ELTH3SXxK z*cj@|Yz+xhyk$evFhaU&3Z(l3$QaU22MO@%Zss_QpFfdp6 z{O}Bj9%PG*jJppWJV=xs{)hK{gmuiy5(Qps%tq0n$rvY04LOadPGhCqcfHHdIk&EF zYJKACb3#ENN(l*FGRT7~!PgGBySY_VxnRB?15r$?fSAh_rxloYP^)k4Z*WX7(NI6( znI1Gh9fDl4uP}lDOEoO{0(Tycc3mCh)22E)KGxTZQ2&UK&W6MO`jQy)c+A>Ydk8+K z#;@C2YnrpQrC7GF23TC6c8i!eq|FdoJhZ37Lp)y=evo|~{Xaf8fUp1geHHCVUCtg} z@!eVOZ*!@Ww)fE^^2aCm(ONeCNzh7gyV9ZA;-k2E&S)YC3y%M7>L7km2>%+Ej9PJl zi(@l_k6G4gT1HClq22JUOvmX%x@uW>+?zZ2n-LIOz}CeL06ata-~ID{ew~=pE#1Pr zXWHP4u4pUKHUQ8Eks72H6H|Ra+%~cYw@ytz$nkD};wJUctj>}jLAG^rr zi?%}IpHDf3dRTcr=N?~<-*zoRDSDdzc9%b5329}C4&ar+a*<$4>z&^_hWK&UVrBPJ zBGHZv$Pedn91;I}I+%{=KS!TAC+6{jaG&!IJe&We|0qflzPakyLom5J@Zzo*H8t@x zf6_=`@{VzOzc~zBGnVa`X4ge{9%)&N7Ci;fi1_%IS8C=5uFz??Zky{}X0QLBvd%ml z%IN?5Bg&F&iLviXQPynPl5Gl+C9<1A+4o(Dh-@JxdnA#eQDp21jWx->C1l^%2)~c- z?|WU(^IXqd{=3J_nfpHH+~<7WulM^Ny3bz8na|0QUNrS`#Tr-2ZEL zKC%q7XU{V9o?V})I;dSu-3=~RG1{=RjzaKL5K*Y*-#?cguHSMq(@4$AA#>P1zwh3s zjlwyZPbwFi-^Ci6(q42Qd=VK+PMJuesY0j8Nlt`I+%{jWwLg-XcBXK(u|RP)Zu`^1}FF*GDN^kz!Mi0dN%_g%SEcx>@2pLPZ+BY6u~Q`7X``K^FjuNCF0 zuB5=g8Wk<~GhfriBV%?lN# zSdy7012#eWn^uK#x`HVUTkWRyXr7eEy?KY#Y%bfrBVD^1HxO$bHL7}6(#v?=iKY3s z{DLV*4K56IN&@VN9k%*=#yz9k-;)l|O(jI*wRK0Ov*qGZqd{{X$$^_$PlH{o>kDr@ zd6q3dyfWcj)9*7ARL3{U#r&RZd&a4G(V^Dz@^tc{gvDLf`<{<;`8S( z(D9E~4A&m$M5ywvCy^s+u&F)nk9fKsdcLca#w4ILwPLH*ldm+-^t}+O`xqf`Q~jFF z{?cT_L%k^6!VcsU^dzvC@e8!nY+BYI*c`iyQ1)CcUGOGqK_F>PQHF+E%S6tIS($HI zo1>BOlOz$ySa0*~1$+!L)%LWq=0FhsPZK^KXgL4K8CsR10dix~(Ek0Kr45@&wCGsx zb7I0x>ttfa1Dc(PP_Sjoek~g~zrJ04ore2@2VyJQsm)nsvuc$sQ?p_k=#aKr3 z1-G>E_#*3%$|a%V2S&1bdJ0`>Q(Aef6_3i#ky2oXI=*a0?+8{84)?q7srJnmQ8lx6 z-Qth+#_be2Dt68q4aT=}XxY&!`d3UUH(rgL@pJ3CdGFdYerz6m3sSP_Ij@unh&3%=?Cvq@=m| zYBcTEC9^w7*ssdIVzmu+o{==6(|i{4DzLlNl=^6=TcE=_8Uy)=c&tajL1|XdcUngG znnL-&UD|Qv1;%$Z>&XYsTP) zslMg>?~cW+|54klrQ_P5YTokNhu^2Eb+nN-gv+0kLW&Bi-gG*M#j)GTdw+O1Oq@q# zbw;{g$5j>7Z4peah-bee4?Hc*~nU_od zHI}=srScB3ipl9bVWNZ7CVF-Ulb2Un(6v=>_yX=vzf2($_Y7Q$QtDFjCNMv@DN|>8 zZ!Ih^T9=y>l-H=P$C51fb9v|A@*1jN=Hrr?w}*|^{>#B$?>O8=Rs;f#(A0XOy>zEz z*~33$03nKyiEO?Wd3dOcLYcIFx<^2^J-x|sC3`Gv_5RH>#Y0Jg=_=-z&La53BR;gW zab4Tt2=*H9NZT!#zOaL?5U zmHaxTI(%!Ai&8}~d-bsLD13^q97Pm*@HS4V;^_M}hkOLWYI*f|Z)ROwM>6rT=L>%E zrR|Bb-H^(4R}GzS1){0vX>)`I%rdO(_E#KEPf|sYG)33k|3z|R_6;K?89C0@*JVC$ z)2^#St9|@Ay7HA!m!*6NfiH#|@maw_N0bcr_(dn?P1vlz_V(QH_Q0Nht;Ka3i@$&C zF9$x5X!1aY+5=S1))BnCtQ2#Gr3r^G_#nL6{N*Fz0it0&>6v^^jSz*!)hekHnwiJ@Tji_u2kOIvv_c%|buNo0 z1gq-d!c)pOlkyq~Y15+dcfFR-MC~}YUdtI30#pg82y)g@_OQrA;r}O z=851X!XXlg#}Xm>4YJ=h&CY-SnPoB1?(y1*Vx(>tiTK(=*^FFOG!Ra2qPXoxo^&w%xM+!Fz1aAx9~eI5Z^dc$vTxi>)Zu(8;=c^)d{P zr%D!1iLwz^7@I-YhaapO-|HO?*iy_0RoO>m+NPa_4TeLrl86&bb+^s0=3b1T7gul+dxlOOSK?bhKNn@R*e*&D5%bP4d`?f2IbdL8F zm3mzMAbt(mr*?JY@f!mpd_1(WoJs>BA~t349!T?uBwkleFvLr78Bj2r>Ce9 z*48_FF9l1B4F`f%M@R@?-Q;Zs7kB;E#03OTX8a%1NfbJFA^w$=f-;p0e0Q&{d$C2* z10n9%A_nxRU&%~zx6k3Ge(95bYxO`@k#tlhPV6TubN$1``QNy+INrKX3zoumn*!C{ zM|+H`9189Qc}=H7yAAuD_Oh3b4@VwwlRu*SLP4QWk~6A9Nhi$@lf>WC&($42<`^4W z{N_Wue;Rn}U{@}NR=Ly?0K+%?8W}G7g;rtqiyz^8cP!B8DbgYPdg0aOQfEW!it1V- z(Y4o&_Y?FxCRgJ5?b~e$_bVf=$>_OPn7O#tkRj9q-*aKen%q`)TKe}ru{-L`tS(fy z=+7BNBrbSXk1UL&JD53d;}>jYp$9WL-{3lyGu)EHVI%I=b) z;<#NoST>cS)VQ`3<;t*qDNFXUJ*=tU=N}Hvy114oP4omsGsfX$M;9HO9Sb-7uhDpo zA4R}jIBm)O5yqp!YzJ=|S7GdFd`dvDR$APcV?|?`JdUZj*n;w3x?Kt74CM^aWk(*+T?tjAyoL5l?7Dg+-X(?**_QPg8uzfQE6V ziCVob7}%7^$T9YF+87|T+v$jZ*}g^hW$PDv`o$kdimc&QR6=hz2>*V#F6CvQQ^9z5j30H@f5M|ly&iFH&u;9Mb^>L>kRdc zp6A9o-C5glAXx+-77EW?v7-6UQPmJ+B$Ex>+Tp6SjAb}D1UcPUH3s-EN{b4<<}v1= z(qW_H=BxgFxbWT=gn&ytBX;6x^lIzWD<}K3P~=|E`qd!VRau!B=}lKnNlHw(JNi(G z*IYL2c(VkAZuOXpRJyIn9~sDIx=TH=U;r>;GRc~q z|HAu5i1?D+ep^(yJ}D|mnBgpf49GlVs2*nOyd7BVlU&9ckiu@~x-NY)gj|Aqug^g$ zoeyPWlG?>4XwIbD({opm^=oymXv?bt*vD6nEPGUC=)48eJD?V`GF>{mqDzWv6s2r+ zf5iC>_a5*`!6aVV9>~m_ZwrlyuiKd9{7HlmZNX!c^>nXsMT_ov=L%tdeIxV8T$8_z zy`cXfXS754X}sy~k+)D(z^YH z%nBRC^;s(7M*#ZQ0c(%BCM4ttwi8Ss6aaz5tn~P}TY_i+RPRrBwyP)-fJop{{XumQ zInk@ZJek+CH=TTYzjvU-^hIJKC+Y`C!ccZsqpJoTHXj2{1e`EfuHIYJzS8;w$`_3a zKp4CUAxRVF3e%GIFx>&`Baz+-rXmnu=?Iplrq@7lNG3>Pz9m{7ZM;xmfkSD4j+&&t z)k?bqHhH@0EECXWoq*y6AVe<(tXJlr-NL3XUb&J5wLsx^KzpHNtD~)bIuy$LJP{xt zpv#9+ub2;;yW9NJ;0R7hOw18%1GO3WO9lT8On9TH_rlNN;bC_5PeMe2_sq>tAm{W> z24-fwO*2L1$k+ix^=bVx2&KdM+b7A)Ux4OsLH!m?PL%*l#kvOvD|_-L9| z!OqUk$|azV!MOz?wR@mx0F8$cMgHjR6>EVq76L4DDB+;ZPH9v?cgxABxO>+UqC_FW z^DENOPy_BBpoc(t7RtAeBO`$mtg}a_3Iiy4XX9Yv*n)=S#~grTPhvoV8*-|c%?bpk zm?s#VLEo{!dtGc9T=r>gZVp}zoB%)i(XVi7jEN2k)rdSFd}288TeAX`(ziK!9TbgX z&<=!zl6fyexgIQN5X%iUWV5;;f9kvi0jt~QR|bHzXAfFygiR2oo+hO)D03slT4gVvi%SeJu^fP_o29h&z_>Hu+L(tmtvord}V z6lc^vn7q~WysF2*rv+UHs+LG}LTh>8t_xf#b3WekiJok~-_copx%TJ^*9n~;0Cgs( zrmAmj%7@IfT}V12gn#^tM<7n`o;)K!AUg;wsAGm3z{UE;;i0dO=TL!${&4xzK#he6 zp$vG3z?CXebd7C00}!`8J=cGnNbH7eAR$R4ji2->FfD8DgRX<3M8{f!)Cpc#t61WA zhXEyy_#ZbVVp+Sxh0N(Dv` zti>=4fHY0Dt>5VxuiTi7;=qrsl$D7lF`<_>{{msL>~jsVC-4tW_?DkMfEk`E0E=d@yYsj2*Yd`y&Ql0bZW2nqxHnf&U2Ct|?)@S5w}vn8VU7r7}l58n_+yl8yOfv zk~laBTnD&8Gz9BlzAy?hIF{OQH2|0bUIrp1Aa(OVtQ>5#i&Ph@>d|ZW{<|pOogBx) z&T3%TSKkvZcJ%xEU%`A%GHIpoL32K7%z2W@$P_#t4?h-EXZY^j>WRY@fa)rpN7VOq zEc(BHdZ2XFvx1cgqqJ&RAy#hC)7H^haaitrqpG*`N|SPv+OPZa4#NC7t6&EtDuZ|h zW_^&H;RSYVpsh~kx9z-ICy?eqDppV8jcS^7lX;b%ez)Y_40R+9CysMp_<2!H52jd8 z4-d%t&4dW&T0kU#&OZ}w4Fvs|p*RriAnX14V|NDyu+tFdv!Ne9RD1wqBB*z_jB3Fk z2OAU`%`*goQzy)C)x{VPW#AJa8eJMWWe>AD9?K!;HTRg&Vz0}$P9LVz-_F49K(io# z19J@?;-HMi3yrg!ieI?9;|1~aaOB9kqrDw%(m(08h3j#d|NAxEV?^-s9(qUgp`N)+$CuMxcPCK4?1(vDRVL)S`E20)qw{Ag)v4DRFBPQkM<_2f%cXK|7`;e9OhetgC z<967aeT0!@b~W}rp{RLLkR0*A!D0Bbd!ArS{)OyrMh=eSL3F}1`Iy)F1qHvmyrVWY zJZubon_WdAMx6kO6>>vBybgfpVsxy~=aA>j(!1_i7R4YxXef*)5D1$ljd2*1i0OZ( zxhLRi0O0J|GO$TN32YO3fT4o~+Z<`x;-Vto(eeyw-wM8HIwMs*lJ-K%Zif)BnMc1TN8GO=?A&ZMVHjj5L{LdV2Sj> z7!vhAKoT)3>DzWD+(IDf{5lQ4*2^-dAsk%6U+F({tAE$V_J!sRZzmwj-U9Ro-TIlW zEI6mCX0w2ol%~F0wxB$5q*6s(1J52g`Cto+@k}XR8OX2z`y%+aP(GFc^KU>xg8@En zQoK)%Us2B8VkjLrXdtErQg$7F9{>Wz02BcBwenH#kgV43dhXVV9u0P}wdZ#&Oe&mA z3=DprxSGN_{{7Nn=}Y)7arR`P9RTnA&*JF+UxELh)zlG3TV)=U^H@z0@ItBSsA5&D G9{mp%Cp}jH literal 0 HcmV?d00001 diff --git a/docs/images/robot_log_example.png b/docs/images/robot_log_example.png new file mode 100644 index 0000000000000000000000000000000000000000..6c15a031e26eae47fed53b21a1e69e2f7bfa89db GIT binary patch literal 158079 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 De;ua! literal 0 HcmV?d00001 diff --git a/docs/images/robot_report_example.png b/docs/images/robot_report_example.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf36d8766753d08938be73c87e958f4c8d56068 GIT binary patch literal 183065 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�b7X;9Qeq&}J;TV~ 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� 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 Ee{B@pxc~qF literal 0 HcmV?d00001 diff --git a/docs/test_plan/README.md b/docs/test_plan/README.md new file mode 100644 index 0000000..d250997 --- /dev/null +++ b/docs/test_plan/README.md @@ -0,0 +1,16 @@ +[**[Return To Main]**] + +# Testplans +List of Common API Services implemented: +* [Api Invoker Management](./api_invoker_management/README.md) +* [Api Provider Management](./api_provider_management/README.md) +* [Api Publish Service](./api_publish_service/README.md) +* [Api Discover Service](./api_discover_service/README.md) +* [Api Events Service](./api_events_service/README.md) +* [Api Security Service](./api_security_service/README.md) +* [Api Logging Service](./api_logging_service/README.md) +* [Api Auditing Service](./api_auditing_service/README.md) +* [Api Access Control Policy](./api_access_control_policy/README.md) + + + [Return To Main]: ../../README.md#test-plan-documentation \ No newline at end of file diff --git a/docs/test_plan/api_access_control_policy/README.md b/docs/test_plan/api_access_control_policy/README.md new file mode 100644 index 0000000..05a9e63 --- /dev/null +++ b/docs/test_plan/api_access_control_policy/README.md @@ -0,0 +1,813 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Access Control Policy](#test-plan-for-capif-api-access-control-policy) +- [Tests](#tests) + - [Test Case 1: Retrieve ACL](#test-case-1-retrieve-acl) + - [Test Case 2: Retrieve ACL with 2 Service APIs published](#test-case-2-retrieve-acl-with-2-service-apis-published) + - [Test Case 3: Retrieve ACL with security context created by two different Invokers](#test-case-3-retrieve-acl-with-security-context-created-by-two-different-invokers) + - [Test Case 4: Retrieve ACL filtered by api-invoker-id](#test-case-4-retrieve-acl-filtered-by-api-invoker-id) + - [Test Case 5: Retrieve ACL filtered by supported-features](#test-case-5-retrieve-acl-filtered-by-supported-features) + - [Test Case 6: Retrieve ACL with aef-id not valid](#test-case-6-retrieve-acl-with-aef-id-not-valid) + - [Test Case 7: Retrieve ACL with service-id not valid](#test-case-7-retrieve-acl-with-service-id-not-valid) + - [Test Case 8: Retrieve ACL with service-api-id and aef-id not valid](#test-case-8-retrieve-acl-with-service-api-id-and-aef-id-not-valid) + - [Test Case 9: Retrieve ACL without SecurityContext created previously by Invoker](#test-case-9-retrieve-acl-without-securitycontext-created-previously-by-invoker) + - [Test Case 10: Retrieve ACL filtered by api-invoker-id not present](#test-case-10-retrieve-acl-filtered-by-api-invoker-id-not-present) + - [Test Case 11: Retrieve ACL with APF Certificate](#test-case-11-retrieve-acl-with-apf-certificate) + - [Test Case 12: Retrieve ACL with AMF Certificate](#test-case-12-retrieve-acl-with-amf-certificate) + - [Test Case 13: Retrieve ACL with Invoker Certificate](#test-case-13-retrieve-acl-with-invoker-certificate) + - [Test Case 14: No ACL for invoker after be removed](#test-case-14-no-acl-for-invoker-after-be-removed) + + + + +# Test Plan for CAPIF Api Access Control Policy +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Retrieve ACL +* **Test ID**: ***capif_api_acl-1*** +* **Description**: + + This test case will check that an API Provider can retrieve ACL from CAPIF +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. contain only one object. + 2. apiInvokerId must match apiInvokerId registered previously. + + +## Test Case 2: Retrieve ACL with 2 Service APIs published +* **Test ID**: ***capif_api_acl-2*** +* **Description**: + + This test case will check that an API Provider can retrieve ACL from CAPIF for 2 different serviceApis published. +* **Pre-Conditions**: + + * API Provider had two Service API Published on CAPIF + * API Invoker had a Security Context for both Service APIs published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_2 + * Store *serviceApiId* + * Use APF Certificate + + 4. Perform [Invoker Onboarding] store apiInvokerId + 5. Discover published APIs + 6. Create Security Context for this Invoker for both published APIs + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 7. Provider Retrieve ACL for serviceApiId1 + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use AEF Provider Certificate + + 8. Provider Retrieve ACL for serviceApiId2 + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId2}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 and service_2 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information for service_1. + 7. Provider Get ACL information for service_2. + +* **Expected Result**: + + 1. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. contain one object. + 2. apiInvokerId must match apiInvokerId registered previously. + +## Test Case 3: Retrieve ACL with security context created by two different Invokers +* **Test ID**: ***capif_api_acl-3*** +* **Description**: + + This test case will check that an API Provider can retrieve ACL from CAPIF containing 2 objects. +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * Two API Invokers had a Security Context for same Service API published by provider. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker for both published APIs + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Repeat previous 3 steps in order to have a new Invoker. + + 7. Provider Retrieve ACL for serviceApiId + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 and service_2 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. Contain two objects. + 2. One object must match with apiInvokerId1 and the other one with apiInvokerId2 an registered previously. + +## Test Case 4: Retrieve ACL filtered by api-invoker-id +* **Test ID**: ***capif_api_acl-4*** +* **Description**: + + This test case will check that an API Provider can retrieve ACL filtering by apiInvokerId from CAPIF containing 1 objects. +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * Two API Invokers had a Security Context for same Service API published by provider. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 4. Perform [Invoker Onboarding] store apiInvokerId + 6. Discover published APIs + 7. Create Security Context for this Invoker for both published APIs + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 8. Repeat previous 3 steps in order to have a new Invoker. + + 9. Provider Retrieve ACL for serviceApiId + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&api-invoker-id={apiInvokerId1}* + * Use *serviceApiId*, *aefId* and apiInvokerId1 + * Use AEF Provider Certificate + + 10. Provider Retrieve ACL for serviceApiId + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&api-invoker-id={apiInvokerId2}* + * Use *serviceApiId*, *aefId* and apiInvokerId2 + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 and service_2 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information with query parameter indicating first api-invoker-id. + 7. Provider Get ACL information with query parameter indicating second api-invoker-id. + +* **Expected Result**: + + 1. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. Contain one objects. + 2. Object must match with apiInvokerId1. + + 2. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. Contain one objects. + 2. Object must match with apiInvokerId2. + +## Test Case 5: Retrieve ACL filtered by supported-features +* **Test ID**: ***capif_api_acl-5*** +* **Description**: + **CURRENTLY NOT SUPPORTED FEATURE** + + This test case will check that an API Provider can retrieve ACL filtering by supportedFeatures from CAPIF containing 1 objects. + +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * Two API Invokers had a Security Context for same Service API published by provider. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker for both published APIs + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Repeat previous 3 steps in order to have a new Invoker. + + 7. Provider Retrieve ACL for serviceApiId + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&supported-features={apiInvokerId1}* + * Use *serviceApiId*, *aefId* and apiInvokerId1 + * Use AEF Provider Certificate + + 8. Provider Retrieve ACL for serviceApiId + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&supported-features={apiInvokerId2}* + * Use *serviceApiId*, *aefId* and apiInvokerId2 + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 and service_2 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information with query parameter indicating first supported-features. + 7. Provider Get ACL information with query parameter indicating second supported-features. + +* **Expected Result**: + + 1. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. Contain one objects. + 2. Object must match with supportedFeatures1. + + 2. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. Contain one objects. + 2. Object must match with supportedFeatures1. + + +## Test Case 6: Retrieve ACL with aef-id not valid +* **Test ID**: ***capif_api_acl-6*** +* **Description**: + + This test case will check that an API Provider can't retrieve ACL from CAPIF if aef-id is not valid +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${AEF_ID_NOT_VALID}* + * Use *serviceApiId* and *AEF_ID_NOT_VALID* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. ACL Response: + 1. **404 Not Found** Response. + 2. body returned must accomplish **Problem Details** data structure. + 3. apiInvokerPolicies must: + * status **404** + * title with message "Not Found" + * detail with message "No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". + * cause with message "Wrong id". + + +## Test Case 7: Retrieve ACL with service-id not valid +* **Test ID**: ***capif_api_acl-7*** +* **Description**: + + This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id is not valid +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${aef_id}* + * Use *NOT_VALID_SERVICE_API_ID* and *aef_id* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. ACL Response: + 1. **404 Not Found** Response. + 2. body returned must accomplish **Problem Details** data structure. + 3. apiInvokerPolicies must: + * status **404** + * title with message "Not Found" + * detail with message "No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". + * cause with message "Wrong id". + +## Test Case 8: Retrieve ACL with service-api-id and aef-id not valid +* **Test ID**: ***capif_api_acl-8*** +* **Description**: + + This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id and aef-id are not valid +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${AEF_ID_NOT_VALID}* + * Use *NOT_VALID_SERVICE_API_ID* and *aef_id* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. ACL Response: + 1. **404 Not Found** Response. + 2. body returned must accomplish **Problem Details** data structure. + 3. apiInvokerPolicies must: + * status **404** + * title with message "Not Found" + * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". + * cause with message "Wrong id". + + +## Test Case 9: Retrieve ACL without SecurityContext created previously by Invoker +* **Test ID**: ***capif_api_acl-9*** +* **Description**: + + This test case will check that an API Provider can't retrieve ACL if no invoker had requested Security Context to CAPIF +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker created but no Security Context for Service API published had been requested. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + + 5. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. ACL Response: + 1. **404 Not Found** Response. + 2. body returned must accomplish **Problem Details** data structure. + 3. apiInvokerPolicies must: + * status **404** + * title with message "Not Found" + * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". + * cause with message "Wrong id". + +## Test Case 10: Retrieve ACL filtered by api-invoker-id not present +* **Test ID**: ***capif_api_acl-10*** +* **Description**: + + This test case will check that an API Provider get not found response if filter by not valid api-invoker-id doesn't match any registered ACL. +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&api-invoker-id={NOT_VALID_API_INVOKER_ID}* + * Use *serviceApiId*, *aefId* and *NOT_VALID_API_INVOKER_ID* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. ACL Response: + 1. **404 Not Found** Response. + 2. body returned must accomplish **Problem Details** data structure. + 3. apiInvokerPolicies must: + * status **404** + * title with message "Not Found" + * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". + * cause with message "Wrong id". + +## Test Case 11: Retrieve ACL with APF Certificate +* **Test ID**: ***capif_api_acl-11*** +* **Description**: + + This test case will check that an API Provider can't retrieve ACL from CAPIF using APF Certificate +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use APF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. Response to Logging Service must accomplish: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 401 + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "Certificate not authorized". + +## Test Case 12: Retrieve ACL with AMF Certificate +* **Test ID**: ***capif_api_acl-12*** +* **Description**: + + This test case will check that an API Provider can't retrieve ACL from CAPIF using AMF Certificate +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use AMF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. Response to Logging Service must accomplish: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 401 + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "Certificate not authorized". + +## Test Case 13: Retrieve ACL with Invoker Certificate +* **Test ID**: ***capif_api_acl-13*** +* **Description**: + + This test case will check that an API Provider can't retrieve ACL from CAPIF using Invoker Certificate +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* + * Use *serviceApiId* and *aefId* + * Use Invoker Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information. + +* **Expected Result**: + + 1. Response to Logging Service must accomplish: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 401 + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "Certificate not authorized". + +## Test Case 14: No ACL for invoker after be removed +* **Test ID**: ***capif_api_acl-14*** +* **Description**: + + This test case will check that ACLs are removed after invoker is removed. +* **Pre-Conditions**: + + * API Provider had a Service API Published on CAPIF + * API Invoker had a Security Context for Service API published and ACL is present + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Store *serviceApiId* + * Use APF Certificate + + 3. Perform [Invoker Onboarding] store apiInvokerId + 4. Discover published APIs + 5. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + + 6. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&api-invoker-id={api-invoker-id}* + * Use *serviceApiId*, *aefId* and *api-invoker-id* + * Use AEF Provider Certificate + 7. Remove Invoker from CAPIF + 8. Provider Retrieve ACL + * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&api-invoker-id={api-invoker-id}* + * Use *serviceApiId*, *aefId* and *api-invoker-id* + * Use AEF Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Provider at CCF. + 2. Publish a provider API with name service_1 + 3. Register and onboard Invoker at CCF + 4. Store signed Certificate + 5. Create Security Context + 6. Provider Get ACL information of invoker. + 7. Remove Invoker from CAPIF. + 8. Provider Get ACL information of invoker. + +* **Expected Result**: + 1. ACL Response: + 1. **200 OK** Response. + 2. body returned must accomplish **AccessControlPolicyList** data structure. + 3. apiInvokerPolicies must: + 1. contain only one object. + 2. apiInvokerId must match apiInvokerId registered previously. + + 2. ACL Response: + 1. **404 Not Found** Response. + 2. body returned must accomplish **Problem Details** data structure. + 3. apiInvokerPolicies must: + * status **404** + * title with message "Not Found" + * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: None and supportedFeatures: None". + * cause with message "Wrong id". + + + +[Return To All Test Plans]: ../README.md + +[service api description]: ../api_publish_service/service_api_description_post_example.json "Service API Description Request" +[publisher register body]: ../api_publish_service/publisher_register_body.json "Publish register Body" +[service security body]: ./service_security.json "Service Security Request" +[security notification body]: ./security_notification.json "Security Notification Request" +[access token req body]: ./access_token_req.json "Access Token Request" +[example]: ./access_token_req.json "Access Token Request Example" +[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" +[provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" diff --git a/docs/test_plan/api_access_control_policy/service_api_description_post_example.json b/docs/test_plan/api_access_control_policy/service_api_description_post_example.json new file mode 100644 index 0000000..b725b42 --- /dev/null +++ b/docs/test_plan/api_access_control_policy/service_api_description_post_example.json @@ -0,0 +1,113 @@ +{ + "apiName": "service_1", + "aefProfiles": [ + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + }, + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + } + ], + "description": "string", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" +} \ No newline at end of file diff --git a/docs/test_plan/api_auditing_service/README.md b/docs/test_plan/api_auditing_service/README.md new file mode 100644 index 0000000..bd3204c --- /dev/null +++ b/docs/test_plan/api_auditing_service/README.md @@ -0,0 +1,244 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Auditing Service](#test-plan-for-capif-api-auditing-service) +- [Tests](#tests) + - [Test Case 1: Get a CAPIF Log Entry.](#test-case-1-creates-a-new-individual-capif-log-entry) + + +# Test Plan for CAPIF Api Auditing Service +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Get CAPIF Log Entry. +* Test ID: ***capif_api_auditing-1*** +* Description: + + This test case will check that a CAPIF AMF can get log entry to Logging Service +* Pre-Conditions: + + * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + * Log Entry exist in CAPIF + +* Information of Test: + + 1. Perform [provider onboarding], [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Create Log Entry: + - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + - body [log entry request body] + - Use AEF Certificate + + 4. Get Log: + 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}* + 2. Use AMF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + 4. Get Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **200 OK** + 2. Response Body must follow **InvocationLog** data structure with: + * aefId + * apiInvokerId + * logs + +## Test Case 2: Get CAPIF Log Entry With no Log entry in CAPIF. +* Test ID: ***capif_api_auditing-2*** +* Description: + + This test case will check that a CAPIF AEF can create log entry to Logging Service +* Pre-Conditions: + + * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + + +* Information of Test: + + 1. Perform [provider onboarding], [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 4. Get Log: + 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}* + 2. Use AMF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Get Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found Log Entry in CAPIF". + * cause with message "Not Exist Logs with the filters applied". + + +## Test Case 3: Get CAPIF Log Entry without aef-id and api-invoker-id. +* Test ID: ***capif_api_auditing-3*** +* Description: + + This test case will check that a CAPIF AEF can create log entry to Logging Service +* Pre-Conditions: + + * CAPIF provider is no pre-authorised (has no valid AMF cert from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + * Log Entry exist in CAPIF + +* Information of Test: + + 1. Perform [provider onboarding], [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Create Log Entry: + - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + - body [log entry request body] + - Use AEF Certificate + + 4. Get Log: + 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs + 2. Use AMF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + 4. Get Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **400 Bad Request** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 400 + * title with message "Bad Request" + * detail with message "aef_id and api_invoker_id parameters are mandatory". + * cause with message "Mandatory parameters missing". + + +## Test Case 4: Get CAPIF Log Entry with filtter api-version. +* Test ID: ***capif_api_auditing-4*** +* Description: + + This test case will check that a CAPIF AMF can get log entry to Logging Service +* Pre-Conditions: + + * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + * Log Entry exist in CAPIF + +* Information of Test: + + 1. Perform [provider onboarding], [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Create Log Entry: + - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + - body [log entry request body] + - Use AEF Certificate + + 4. Get Log: + 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}&api-version={v1}* + 2. Use AMF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + 4. Get Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **200 OK** + 2. Response Body must follow **InvocationLog** data structure with: + * aefId + * apiInvokerId + * logs + + +## Test Case 5: Get CAPIF Log Entry with filter api-version but not exist in log entry. +* Test ID: ***capif_api_auditing-4*** +* Description: + + This test case will check that a CAPIF AMF can get log entry to Logging Service +* Pre-Conditions: + + * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + * Log Entry exist in CAPIF + +* Information of Test: + + 1. Perform [provider onboarding], [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Create Log Entry: + - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + - body [log entry request body] + - Use AEF Certificate + + 4. Get Log: + 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}&api-version={v58}* + 2. Use AMF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + 4. Get Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * detail with message "Parameters do not match any log entry" + * cause with message "No logs found". + + + +[log entry request body]: ../api_logging_service/invocation_log.json "Log Request Body" + +[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" + +[provider onboarding]: ../common_operations/README.md#register-a-provider "Provider Onboarding" + +[Return To All Test Plans]: ../README.md \ No newline at end of file diff --git a/docs/test_plan/api_discover_service/README.md b/docs/test_plan/api_discover_service/README.md new file mode 100644 index 0000000..3125c88 --- /dev/null +++ b/docs/test_plan/api_discover_service/README.md @@ -0,0 +1,336 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Discover Service](#test-plan-for-capif-discover-service) +- [Tests](#tests) + - [Test Case 1: Discover Published service APIs by Authorised API Invoker](#test-case-1-discover-published-service-apis-by-authorised-api-invoker) + - [Test Case 2: Discover Published service APIs by Non Authorised API Invoker](#test-case-2-discover-published-service-apis-by-non-authorised-api-invoker) + - [Test Case 3: Discover Published service APIs by not registered API Invoker](#test-case-3-discover-published-service-apis-by-not-registered-api-invoker) + - [Test Case 4: Discover Published service APIs by registered API Invoker with 1 result filtered](#test-case-4-discover-published-service-apis-by-registered-api-invoker-with-1-result-filtered) + - [Test Case 5: Discover Published service APIs by registered API Invoker filtered with no match](#test-case-5-discover-published-service-apis-by-registered-api-invoker-filtered-with-no-match) + - [Test Case 6: Discover Published service APIs by registered API Invoker not filtered](#test-case-6-discover-published-service-apis-by-registered-api-invoker-not-filtered) + + +# Test Plan for CAPIF Discover Service +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Discover Published service APIs by Authorised API Invoker +* **Test ID**: ***capif_api_discover_service-1*** +* **Description**: + + This test case will check if NetApp (Invoker) can discover published service APIs. +* **Pre-Conditions**: + * Service APIs are published. + * NetApp was registered previously + * NetApp was onboarded previously with {onboardingId} + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + 3. Request Discover Published APIs: + * Send GET to *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Use Invoker Certificate + +* **Execution Steps**: + + 1. Register Provider at CCF, store certificates and Publish Service API at CCF + 2. Register Invoker and Onboard Invoker at CCF + 3. Discover Service APIs by Invoker + +* **Expected Result**: + + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + 3. Response to Discover Request By Invoker: + 1. **200 OK** response. + 2. Response body must follow **DiscoveredAPIs** data structure: + * Check if DiscoveredAPIs contains the API Published previously + + +## Test Case 2: Discover Published service APIs by Non Authorised API Invoker +* **Test ID**: ***capif_api_discover_service-2*** +* **Description**: + + This test case will check that an API Publisher can't discover published APIs because is not authorized. + +* **Pre-Conditions**: + * Service APIs are published. + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + 3. Request Discover Published APIs by no invoker entity: + * Send GET to *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Use not Invoker Certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API at CCF + 2. Register Invoker and Onboard Invoker at CCF + 3. Discover Service APIs by no invoker entity + +* **Expected Result**: + + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 3. Response to Discover Request By no invoker entity: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 401 + * title with message "Unauthorized" + * detail with message "User not authorized". + * cause with message "Certificate not authorized". + + +## Test Case 3: Discover Published service APIs by not registered API Invoker +* **Test ID**: ***capif_api_discover_service-3*** +* **Description**: + + This test case will check that a not registered invoker is forbidden to discover published APIs. + +* **Pre-Conditions**: + * Service APIs are published. + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + 3. Request Discover Published APIs with not valid apiInvoker: + * Send GET to *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={INVOKER_NOT_REGISTERED}* + * Param api-invoker-id is mandatory + * Using invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API at CCF + 2. Register Invoker and Onboard Invoker at CCF + 3. Discover Service APIs by Publisher + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 3. Response to Discover Request By Invoker: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "API Invoker does not exist". + * cause with message "API Invoker id not found". + + +## Test Case 4: Discover Published service APIs by registered API Invoker with 1 result filtered +* **Test ID**: ***capif_api_discover_service-4*** +* **Description**: + + This test case will check if NetApp (Invoker) can discover published service APIs. +* **Pre-Conditions**: + * At least 2 Service APIs are published. + * NetApp was registered previously + * NetApp was onboarded previously with {onboardingId} + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + 3. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_2 + * Use APF Certificate + 4. Request Discover Published APIs filtering by api-name: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&api-name=service_1* + * Param api-invoker-id is mandatory + * Using invoker certificate + * filter by api-name service_1 + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF + 2. Register Invoker and Onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Discover filtered by api-name service_1 Service APIs by Invoker + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + 2. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + 3. Response to Discover Request By Invoker: + 1. **200 OK** response. + 2. Response body must follow **DiscoveredAPIs** data structure: + * Check if DiscoveredAPIs contains previously registered Service APIs published. + 4. Response to Discover Request By Invoker: + 1. **200 OK** response. + 2. Response body must follow **DiscoveredAPIs** data structure: + * Check if DiscoveredAPIs contains only Service API published with api-name service_1 + + +## Test Case 5: Discover Published service APIs by registered API Invoker filtered with no match +* **Test ID**: ***capif_api_discover_service-5*** +* **Description**: + This test case will check if NetApp (Invoker) can discover published service APIs. +* **Pre-Conditions**: + * At least 2 Service APIs are published. + * NetApp was registered previously + * NetApp was onboarded previously with {onboardingId} + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + 3. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_2 + * Use APF Certificate + 4. Request Discover Published APIs filtering by api-name not published: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&api-name=NOT_VALID_NAME* + * Param api-invoker-id is mandatory + * Using invoker certificate + * filter by api-name NOT_VALID_NAME + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF + 2. Register Invoker and Onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Discover filtered by api-name not published Service APIs by Invoker + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + 2. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + 3. Response to Discover Request By Invoker: + 1. **200 OK** response. + 2. Response body must follow **DiscoveredAPIs** data structure: + * Check if DiscoveredAPIs contains previously registered Service APIs published. + 4. Response to Discover Request By Invoker: + 1. **404 Not Found** response. + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "API Invoker {api_invoker_id} has no API Published that accomplish filter conditions". + * cause with message "No API Published accomplish filter conditions". + + +## Test Case 6: Discover Published service APIs by registered API Invoker not filtered +* **Test ID**: ***capif_api_discover_service-6*** +* **Description**: + + This test case will check if NetApp (Invoker) can discover published service APIs. +* **Pre-Conditions**: + * 2 Service APIs are published. + * NetApp was registered previously + * NetApp was onboarded previously with {onboardingId} + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + 3. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_2 + * Use APF Certificate + 4. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF + 2. Register Invoker and Onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Discover without filter by Invoker + +* **Expected Result**: + + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 3. Response to Discover Request By Invoker: + 1. **200 OK** response. + 2. Response body must follow **DiscoveredAPIs** data structure: + * Check if DiscoveredAPIs contains the 2 previously registered Service APIs published. + + + + [service api description]: ./api_publish_service/service_api_description_post_example.json "Service API **Description** Request" + [publisher register body]: ./api_publish_service/publisher_register_body.json "Publish register Body" + [invoker onboarding body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" + [invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" + [provider request body]: ../api_provider_management/provider_details_post_example.json "API Provider Enrolment Request" + [provider request patch body]: ../api_provider_management/provider_details_enrolment_details_patch_example.json "API Provider Enrolment Patch Request" + [provider getauth body]: ../api_provider_management/provider_getauth_example.json "Get Auth Example" + [invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" + [provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" + + +[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_events_service/README.md b/docs/test_plan/api_events_service/README.md new file mode 100644 index 0000000..417c1aa --- /dev/null +++ b/docs/test_plan/api_events_service/README.md @@ -0,0 +1,265 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Events Service](#test-plan-for-capif-api-events-service) +- [Tests](#tests) + - [Test Case 1: Creates a new individual CAPIF Event Subscription.](#test-case-1-creates-a-new-individual-capif-event-subscription) + - [Test Case 2: Creates a new individual CAPIF Event Subscription with Invalid SubscriberId](#test-case-2-creates-a-new-individual-capif-event-subscription-with-invalid-subscriberid) + - [Test Case 3: Deletes an individual CAPIF Event Subscription](#test-case-3-deletes-an-individual-capif-event-subscription) + - [Test Case 4: Deletes an individual CAPIF Event Subscription with invalid SubscriberId](#test-case-4-deletes-an-individual-capif-event-subscription-with-invalid-subscriberid) + - [Test Case 5: Deletes an individual CAPIF Event Subscription with invalid SubscriptionId](#test-case-5-deletes-an-individual-capif-event-subscription-with-invalid-subscriptionid) + + + +# Test Plan for CAPIF Api Events Service +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Creates a new individual CAPIF Event Subscription. +* Test ID: ***capif_api_events-1*** +* Description: + + This test case will check that a CAPIF subscriber (Invoker or Publisher) can Subscribe to Events +* Pre-Conditions: + + * CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority) + +* Information of Test: + + 1. Perform [Invoker Onboarding] + + 2. Event Subscription: + 1. Send POST to *https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions* + 2. body [event subscription request body] + 3. Use Invoker Certificate + +* Execution Steps: + + 1. Register Invoker and Onboard Invoker at CCF + 2. Subscribe to Events + 3. Retrieve {subscriberId} and {subscriptionId} from Location Header + +* Expected Result: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 2. Response to Event Subscription must accomplish: + 1. **201 Created** + 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} + 3. Response Body must follow **EventSubscription** data structure. + + 3. Event Subscriptions are stored in CAPIF Database + + +## Test Case 2: Creates a new individual CAPIF Event Subscription with Invalid SubscriberId +* Test ID: ***capif_api_events-2*** +* Description: + + This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Subscribe to Events without valid SubcriberId +* Pre-Conditions: + + * CAPIF subscriber is not pre-authorised (has invalid InvokerId or apfId) + +* Information of Test: + + 1. Perform [Invoker Onboarding] + + 2. Event Subscription: + 1. Send POST to *https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_NOT_REGISTERED}/subscriptions* + 2. body [event subscription request body] + 3. Use Invoker Certificate + +* Execution Steps: + + 1. Register Invoker and Onboard Invoker at CCF + 2. Subscribe to Events + +* Expected Result: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 2. Response to Event Subscription must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Invoker or APF or AEF or AMF Not found". + * cause with message "Subscriber Not Found". + + 3. Event Subscriptions are not stored in CAPIF Database + + +## Test Case 3: Deletes an individual CAPIF Event Subscription +* Test ID: ***capif_api_events-3*** +* Description: + + This test case will check that a CAPIF subscriber (Invoker or Publisher) can Delete an Event Subscription +* Pre-Conditions: + + * CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority) + +* Information of Test: + + 1. Perform [Invoker Onboarding] + + 2. Event Subscription: + 1. Send POST to *https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions* + 2. body [event subscription request body] + 3. Use Invoker Certificate + + 3. Remove Event Subscription: + 1. Send DELETE to *https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions* + 2. Use Invoker Certificate + +* Execution Steps: + + 1. Register Invoker and Onboard Invoker at CCF + 2. Subscribe to Events + 3. Retrieve {subscriberId} and {subscriptionId} from Location Header + 4. Remove Event Subscription + +* Expected Result: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 2. Response to Event Subscription must accomplish: + 1. **201 Created** + 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} + 3. Response Body must follow **EventSubscription** data structure. + + 3. Event Subscriptions are stored in CAPIF Database + 4. Remove Event Subscription: + 1. **204 No Content** + + 5. Event Subscription is not present at CAPIF Database. + + +## Test Case 4: Deletes an individual CAPIF Event Subscription with invalid SubscriberId +* Test ID: ***capif_api_events-4*** +* Description: + + This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete to Events without valid SubcriberId +* Pre-Conditions: + + * CAPIF subscriber is pre-authorised (has valid InvokerId or apfId). + * CAPIF subscriber is subscribed to Events. + +* Information of Test: + + 1. Perform [Invoker Onboarding] + + 2. Event Subscription: + 1. Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions + 2. body [event subscription request body] + 3. Use Invoker Certificate + + 3. Remove Event Subcription with not valid subscriber: + 1. Send DELETE to to https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_ID_NOT_VALID}/subscriptions/{subcriptionId} + 2. Use Invoker Certificate + +* Execution Steps: + + 1. Register Invoker and Onboard Invoker at CCF + 2. Subscribe to Events + 3. Retrieve Location Header with subscriptionId. + 4. Remove Event Subscribed with not valid Subscriber. + +* Expected Result: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 2. Response to Event Subscription must accomplish: + 1. 201 Created + 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} + 3. Response Body must follow **EventSubscription** data structure. + + 3. Event Subscriptions are stored in CAPIF Database + 4. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Invoker or APF or AEF or AMF Not found". + * cause with message "Subscriber Not Found". + + +## Test Case 5: Deletes an individual CAPIF Event Subscription with invalid SubscriptionId +* Test ID: ***capif_api_events-5*** +* Description: + + This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete an Event Subscription without valid SubscriptionId +* Pre-Conditions: + + * CAPIF subscriber is pre-authorised (has invalid InvokerId or apfId). + * CAPIF subscriber is subscribed to Events. + +* Information of Test: + + 1. Perform [Invoker Onboarding] + + 2. Event Subscription: + 1. Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions + 2. body [event subscription request body] + 3. Use Invoker Certificate + + 3. Remove Event Subcription with not valid subscriber: + 1. Send DELETE to to https://{CAPIF_HOSTNAME}/capif-events/v1/{subcriberId}/subscriptions/{SUBSCRIPTION_ID_NOT_VALID} + 2. Use Invoker Certificate + +* Execution Steps: + + 1. Register Invoker and Onboard Invoker at CCF + 2. Subscribe to Events + 3. Retrieve Location Header with subscriptionId. + 4. Remove Event Subscribed with not valid Subscriber. + +* Expected Result: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + 2. Response to Event Subscription must accomplish: + 1. **201 Created** + 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} + 3. Response Body must follow **EventSubscription** data structure. + + 3. Event Subscriptions are stored in CAPIF Database + 4. Remove Event Subscription with not valid subscriber: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * detail with message "Service API not existing". + * cause with message "Event API subscription id not found". + + + + +[invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" +[invoker onboard request body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" +[event subscription request body]: ./event_subscription.json "Event Subscription Request" +[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" + + +[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_events_service/event_subscription.json b/docs/test_plan/api_events_service/event_subscription.json new file mode 100644 index 0000000..40dc09b --- /dev/null +++ b/docs/test_plan/api_events_service/event_subscription.json @@ -0,0 +1,31 @@ +{ + "eventFilters": [ + { + "aefIds": ["aefIds", "aefIds"], + "apiIds": ["apiIds", "apiIds"], + "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"] + }, + { + "aefIds": ["aefIds", "aefIds"], + "apiIds": ["apiIds", "apiIds"], + "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"] + } + ], + "eventReq": { + "grpRepTime": 5, + "immRep": true, + "maxReportNbr": 0, + "monDur": "2000-01-23T04:56:07+00:00", + "partitionCriteria": ["string1", "string2"], + "repPeriod": 6, + "sampRatio": 15 + }, + "events": ["SERVICE_API_AVAILABLE", "API_INVOKER_ONBOARDED"], + "notificationDestination": "http://robot.testing", + "requestTestNotification": true, + "supportedFeatures": "aaa", + "websockNotifConfig": { + "requestWebsocketUri": true, + "websocketUri": "websocketUri" + } +} diff --git a/docs/test_plan/api_invoker_management/README.md b/docs/test_plan/api_invoker_management/README.md new file mode 100644 index 0000000..9846c96 --- /dev/null +++ b/docs/test_plan/api_invoker_management/README.md @@ -0,0 +1,306 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Invoker Management](#test-plan-for-capif-api-invoker-management) +- [Tests](#tests) + - [Test Case 1: Onboard NetApp](#test-case-1-onboard-netapp) + - [Test Case 2: Onboard NetApp Already onboarded](#test-case-2-onboard-netapp-already-onboarded) + - [Test Case 3: Update Onboarded NetApp](#test-case-3-update-onboarded-netapp) + - [Test Case 4: Update Not Onboarded NetApp](#test-case-4-update-not-onboarded-netapp) + - [Test Case 5: Offboard NetApp](#test-case-5-offboard-netapp) + - [Test Case 6: Offboard Not previsouly Onboarded NetApp](#test-case-6-offboard-not-previsouly-onboarded-netapp) + - [Test Case 7: Update Onboarded NetApp Certificate](#test-case-7-update-onboarded-netapp-certificate) + + +# Test Plan for CAPIF Api Invoker Management +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Onboard NetApp +* **Test ID**: ***capif_api_invoker_management-1*** +* **Description**: + + This test will try to register new NetApp at CAPIF Core. +* **Pre-Conditions**: + + * NetApp was not registered previously + * NetApp was not onboarded previously + +* **Information of Test**: + + 1. Create public and private key at invoker + + 2. Register of Invoker at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [invoker register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [invoker getauth body] + + 4. Onboard Invoker: + * Send POST to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers* + * Reference Request Body: [invoker onboarding body] + * "onboardingInformation"->"apiInvokerPublicKey": must contain public key generated by Invoker. + * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) + +* **Execution Steps**: + 1. Register Invoker at CCF + 2. Onboard Invoker at CCF + 3. Store signed Certificate + +* **Expected Result**: + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + +## Test Case 2: Onboard NetApp Already onboarded + +* **Test ID**: ***capif_api_invoker_management-2*** +* **Description**: + + This test will check second onboard of same NetApp is not allowed. + +* **Pre-Conditions**: + + * NetApp was registered previously + * NetApp was onboarded previously + +* **Information of Test**: + + 1. Perform [Invoker Onboarding] + + 2. Repeat Onboard Invoker: + * Send POST to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers* + * Reference Request Body: [invoker onboarding body] + * "onboardingInformation"->"apiInvokerPublicKey": must contain public key generated by Invoker. + * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) + +* **Execution Steps**: + 1. Register NetApp at CCF + 2. Onboard NetApp at CCF + 3. Store signed Certificate at NetApp + 4. Onboard Again the NetApp at CCF + +* **Expected Result**: + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + 2. Response to Second Onboard of NetApp must accomplish: + 1. **403 Forbidden** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 403 + * title with message "Forbidden" + * detail with message "Invoker Already registered". + * cause with message "Identical invoker public key". + + +## Test Case 3: Update Onboarded NetApp +* **Test ID**: ***capif_api_invoker_management-3*** +* **Description**: + + This test will try to update information of previous onboard NetApp at CAPIF Core. +* **Pre-Conditions**: + + * NetApp was registered previously + * NetApp was onboarded previously with {onboardingId} + +* **Information of Test**: + + 1. Perform [Invoker Onboarding] + + 2. Update information of previously onboarded Invoker: + * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* + * Reference Request Body is: [put invoker onboarding body] + * "notificationDestination": "*http://host.docker.internal:8086/netapp_new_callback*", + +* **Execution Steps**: + + 1. Register Invoker at CCF + 2. Onboard Invoker at CCF + 3. Store signed Certificate + 4. Update Onboarding Information at CCF with a minor change on "notificationDestination" + +* **Expected Result**: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + 2. Response to Update Request (PUT) with minor change must contain: + 1. **200 OK** response. + 2. notificationDestination on response must contain the new value + + +## Test Case 4: Update Not Onboarded NetApp +* **Test ID**: ***capif_api_invoker_management-4*** +* **Description**: + + This test will try to update information of not onboarded NetApp at CAPIF Core. +* **Pre-Conditions**: + + * NetApp was registered previously + * NetApp was not onboarded previously + +* **Information of Test**: + + 1. Perform [Invoker Onboarding] + + 2. Update information of not onboarded Invoker: + * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}* + * Reference Request Body is: [put invoker onboarding body] + +* **Execution Steps**: + + 1. Register Invoker at CCF + 2. Onboard Invoker at CCF + 3. Update Onboarding Information at CCF of not onboarded + +* **Expected Result**: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response to Update Request (PUT) must contain: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Please provide an existing Netapp ID". + * cause with message "Not exist NetappID". + + + +## Test Case 5: Offboard NetApp +* **Test ID**: ***capif_api_invoker_management-5*** +* **Description**: + + This test case will check that a Registered NetApp can be deleted. +* **Pre-Conditions**: + + * NetApp was registered previously + * NetApp was onboarded previously + +* **Information of Test**: + + 1. Perform [Invoker Onboarding] + + 2. Offboard: + * Send Delete to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* + +* **Execution Steps**: + + 1. Register Invoker at CCF + 2. Onboard Invoker at CCF + 3. Offboard Invoker at CCF + +* **Expected Result**: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response to Offboard Request (DELETE) must contain: + 1. **204 No Content** + + +## Test Case 6: Offboard Not previsouly Onboarded NetApp +* **Test ID**: ***capif_api_invoker_management-6*** +* **Description**: + + This test case will check that a Non-Registered NetApp cannot be deleted +* **Pre-Conditions**: + + * NetApp was registered previously + * NetApp was not onboarded previously + +* **Information of Test**: + + 1. Perform [Invoker Onboarding] + + 2. Offboard: + * Send Delete to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}* + +* **Execution Steps**: + + 1. Register Invoker at CCF + 2. Offboard Invoker at CCF + +* **Expected Result**: + + 1. Response to Offboard Request (DELETE) must contain: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Please provide an existing Netapp ID". + * cause with message "Not exist NetappID". + +## Test Case 7: Update Onboarded NetApp Certificate +* **Test ID**: ***capif_api_invoker_management-7*** +* **Description**: + + This test will try to update public key and get a new signed certificate by CAPIF Core. +* **Pre-Conditions**: + + * NetApp was registered previously + * NetApp was onboarded previously with {onboardingId} and {public_key_1} + +* **Information of Test**: + + 1. Perform [Invoker Onboarding] with public_key_1. + + 2. Create {public_key_2} + + 3. Update information of previously onboarded Invoker: + * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* + * Reference Request Body is: [put invoker onboarding body] + * ["onboardingInformation"]["apiInvokerPublicKey"]: {public_key_2}, + * Store new certificate. + + 4. Update information of previously onboarded Invoker Using new certificate: + * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* + * Reference Request Body is: [put invoker onboarding body] + * "notificationDestination": "*http://host.docker.internal:8086/netapp_new_callback*", + * Use new invoker certificate + +* **Execution Steps**: + + 1. Register Invoker at CCF + 2. Onboard Invoker at CCF + 3. Store signed Certificate + 4. Update Onboarding Information at CCF with new public key + 5. Update Onboarding Information at CCF with minor change + +* **Expected Result**: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + 2. Response to Update Request (PUT) with new public key: + 1. **200 OK** response. + 2. apiInvokerCertificate with new certificate on response -> store to use. + 3. Response to Update Request (PUT) with minor change must contain: + 1. **200 OK** response. + 2. notificationDestination on response must contain the new value + + + + +[invoker onboarding body]: ./invoker_details_post_example.json "API Invoker Request" +[invoker register body]: ./invoker_register_body.json "Invoker Register Body" +[put register body]: ./invoker_details_put_example.json "API Invoker Update Request" +[invoker getauth body]: ./invoker_getauth_example.json "Get Auth Example" + +[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" + +[Return To All Test Plans]: ../README.md \ No newline at end of file diff --git a/docs/test_plan/api_invoker_management/invoker_details_post_example.json b/docs/test_plan/api_invoker_management/invoker_details_post_example.json new file mode 100644 index 0000000..c306a17 --- /dev/null +++ b/docs/test_plan/api_invoker_management/invoker_details_post_example.json @@ -0,0 +1,15 @@ +{ + "notificationDestination": "http://host.docker.internal:8086/netapp_callback", + "supportedFeatures": "fffffff", + "apiInvokerInformation": "ROBOT_TESTING_INVOKER", + "websockNotifConfig": { + "requestWebsocketUri": true, + "websocketUri": "websocketUri" + }, + "onboardingInformation": { + "apiInvokerPublicKey": "{PUBLIC_KEY}", + "onboardingSecret": "onboardingSecret", + "apiInvokerCertificate": "apiInvokerCertificate" + }, + "requestTestNotification": true +} diff --git a/docs/test_plan/api_invoker_management/invoker_details_put_example.json b/docs/test_plan/api_invoker_management/invoker_details_put_example.json new file mode 100644 index 0000000..37a1eef --- /dev/null +++ b/docs/test_plan/api_invoker_management/invoker_details_put_example.json @@ -0,0 +1,393 @@ +{ + "notificationDestination": "http://host.docker.internal:8086/netapp_new_callback", + "supportedFeatures": "fffffff", + "apiInvokerInformation": "ROBOT_TESTING_INVOKER", + "websockNotifConfig": { + "requestWebsocketUri": true, + "websocketUri": "websocketUri" + }, + "onboardingInformation": { + "apiInvokerPublicKey": "{PUBLIC_KEY}", + "onboardingSecret": "onboardingSecret", + "apiInvokerCertificate": "apiInvokerCertificate" + }, + "requestTestNotification": true, + "apiList": [ + { + "serviceAPICategory": "serviceAPICategory", + "ccfId": "ccfId", + "apiName": "apiName", + "shareableInfo": { + "capifProvDoms": ["capifProvDoms", "capifProvDoms"], + "isShareable": true + }, + "supportedFeatures": "fffffff", + "description": "description", + "apiSuppFeats": "fffffff", + "apiId": "apiId", + "aefProfiles": [ + { + "securityMethods": ["PSK"], + "versions": [ + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + }, + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + } + ], + "aefId": "aefId", + "interfaceDescriptions": [ + { + "securityMethods": ["PSK"], + "port": 5248, + "ipv4Addr": "ipv4Addr" + }, + { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } + ] + }, + { + "securityMethods": ["PSK"], + "versions": [ + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + }, + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + } + ], + "aefId": "aefId", + "interfaceDescriptions": [ + { + "securityMethods": ["PSK"], + "port": 5248, + "ipv4Addr": "ipv4Addr" + }, + { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } + ] + } + ], + "pubApiPath": { "ccfIds": ["ccfIds", "ccfIds"] } + }, + { + "serviceAPICategory": "serviceAPICategory", + "ccfId": "ccfId", + "apiName": "apiName2", + "shareableInfo": { + "capifProvDoms": ["capifProvDoms", "capifProvDoms"], + "isShareable": true + }, + "supportedFeatures": "fffffff", + "description": "description", + "apiSuppFeats": "fffffff", + "apiId": "apiId", + "aefProfiles": [ + { + "securityMethods": ["PSK"], + "versions": [ + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + }, + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + } + ], + "aefId": "aefId", + "interfaceDescriptions": [ + { + "securityMethods": ["PSK"], + "port": 5248, + "ipv4Addr": "ipv4Addr" + }, + { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } + ] + }, + { + "securityMethods": ["PSK"], + "versions": [ + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + }, + { + "apiVersion": "apiVersion", + "resources": [ + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "resourceName": "resourceName", + "custOpName": "custOpName", + "uri": "uri", + "commType": "REQUEST_RESPONSE" + } + ], + "custOperations": [ + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + }, + { + "operations": ["GET"], + "description": "description", + "custOpName": "custOpName", + "commType": "REQUEST_RESPONSE" + } + ], + "expiry": "2000-01-23T04:56:07.000+00:00" + } + ], + "aefId": "aefId", + "interfaceDescriptions": [ + { + "securityMethods": ["PSK"], + "port": 5248, + "ipv4Addr": "ipv4Addr" + }, + { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } + ] + } + ], + "pubApiPath": { "ccfIds": ["ccfIds", "ccfIds"] } + } + ] +} diff --git a/docs/test_plan/api_invoker_management/invoker_getauth_example.json b/docs/test_plan/api_invoker_management/invoker_getauth_example.json new file mode 100644 index 0000000..a66dad5 --- /dev/null +++ b/docs/test_plan/api_invoker_management/invoker_getauth_example.json @@ -0,0 +1,4 @@ +{ + "username": "ROBOT_TESTING_INVOKER", + "password": "password" +} diff --git a/docs/test_plan/api_invoker_management/invoker_register_body.json b/docs/test_plan/api_invoker_management/invoker_register_body.json new file mode 100644 index 0000000..e5bf1fc --- /dev/null +++ b/docs/test_plan/api_invoker_management/invoker_register_body.json @@ -0,0 +1,7 @@ +{ + "password": "password", + "username": "ROBOT_TESTING_INVOKER", + "role": "invoker", + "description": "Testing", + "cn": "ROBOT_TESTING_INVOKER" +} diff --git a/docs/test_plan/api_logging_service/README.md b/docs/test_plan/api_logging_service/README.md new file mode 100644 index 0000000..913a652 --- /dev/null +++ b/docs/test_plan/api_logging_service/README.md @@ -0,0 +1,241 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Logging Service](#test-plan-for-capif-api-logging-service) +- [Tests](#tests) + - [Test Case 1: Creates a new individual CAPIF Log Entry.](#test-case-1-creates-a-new-individual-capif-log-entry) + - [Test Case 2: Creates a new individual CAPIF Log Entry with Invalid aefID](#test-case-2-creates-a-new-individual-capif-log-entry-with-invalid-aefid) + - [Test Case 3: Creates a new individual CAPIF Log Entry with Invalid serviceAPI](#test-case-3-creates-a-new-individual-capif-log-entry-with-invalid-serviceapi) + - [Test Case 4: Creates a new individual CAPIF Log Entry with Invalid apiInvokerId](#test-case-4-creates-a-new-individual-capif-log-entry-with-invalid-apiinvokerid) + + - [Test Case 5: Creates a new individual CAPIF Log Entry with differnted aef_id in body and request](#test-case-5-creates-a-new-individual-capif-log-entry-with-invalid-aefid-in-body) + + +# Test Plan for CAPIF Api Logging Service +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Creates a new individual CAPIF Log Entry. +* Test ID: ***capif_api_logging-1*** +* Description: + + This test case will check that a CAPIF AEF can create log entry to Logging Service +* Pre-Conditions: + + * CAPIF provider is pre-authorised (has valid aefId from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + +* Information of Test: + + 1. Perform [provider onboarding] and [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Log Entry: + 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + 2. body [log entry request body] + 3. Use AEF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **201 Created** + 2. Response Body must follow **InvocationLog** data structure with: + * aefId + * apiInvokerId + * logs + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invocation-logs/v1/{aefId}/logs/{logId}* + + + + +## Test Case 2: Creates a new individual CAPIF Log Entry with Invalid aefId +* Test ID: ***capif_api_logging-2*** +* Description: + + This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId +* Pre-Conditions: + + * CAPIF provider is not pre-authorised (has not valid aefId from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + +* Information of Test: + + 1. Perform [provider onboarding] and [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Log Entry: + 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{not-valid-aefId}/logs* + 2. body [log entry request body] + 3. Use AEF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Exposer not exist". + * cause with message "Exposer id not found". + +## Test Case 3: Creates a new individual CAPIF Log Entry with Invalid serviceAPI +* Test ID: ***capif_api_logging-3*** +* Description: + + This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId +* Pre-Conditions: + + * CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority) + +* Information of Test: + + 1. Perform [provider onboarding] and [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Log Entry: + 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + 2. body [log entry request body with serviceAPI apiName apiId not valid] + 3. Use AEF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Invoker not exist". + * cause with message "Invoker id not found". + + + +## Test Case 4: Creates a new individual CAPIF Log Entry with Invalid apiInvokerId +* Test ID: ***capif_api_logging-4*** +* Description: + + This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId +* Pre-Conditions: + + * CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority) + +* Information of Test: + + 1. Perform [provider onboarding] and [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Log Entry: + 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + 2. body [log entry request body with invokerId not valid] + 3. Use AEF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + +* Expected Result: + + 1. Response to Onboard request must accomplish: + 1. **201 Created** response. + 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. + 3. For each **apiProvFuncs**, we must check: + 1. **apiProvFuncId** is set + 2. **apiProvCert** under **regInfo** is set properly + 5. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* + + 2. Response to Logging Service must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Invoker not exist". + * cause with message "Invoker id not found". + + 3. Log Entry are not stored in CAPIF Database + + +## Test Case 5: Creates a new individual CAPIF Log Entry with Invalid aefId in body +* Test ID: ***capif_api_logging-5*** +* Description: + + This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId in body +* Pre-Conditions: + + * CAPIF provider is pre-authorised (has valid apfId from CAPIF Authority) + * Service exist in CAPIF + * Invoker exist in CAPIF + +* Information of Test: + + 1. Perform [provider onboarding] and [invoker onboarding] + + 2. Publish Service API at CCF: + - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + - body [service api description] with apiName service_1 + - Use APF Certificate + + 3. Log Entry: + 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* + 2. body [log entry request body with bad aefId] + 3. Use AEF Certificate + +* Execution Steps: + 1. Register Provider and Invoker CCF + 2. Publish Service + 3. Create Log Entry + +* Expected Result: + + 1. Response to Logging Service must accomplish: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 401 + * title with message "Unauthorized" + * detail with message "AEF id not matching in request and body". + * cause with message "Not identical AEF id". + + + + + + +[log entry request body]: ./invocation_log.json "Log Request Body" + +[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" + +[provider onboarding]: ../common_operations/README.md#register-a-provider "Provider Onboarding" + +[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_logging_service/invocation_log.json b/docs/test_plan/api_logging_service/invocation_log.json new file mode 100644 index 0000000..ceabcf0 --- /dev/null +++ b/docs/test_plan/api_logging_service/invocation_log.json @@ -0,0 +1,45 @@ +{ + "aefId": "aefId", + "apiInvokerId": "apiInvokerId", + "logs": [ + { + "apiId": "apiId", + "apiName": "apiName", + "apiVersion": "string", + "resourceName": "string", + "uri": "string", + "protocol": "HTTP_1_1", + "operation": "GET", + "result": "string", + "invocationTime": "2023-03-30T10:30:21.404Z", + "invocationLatency": 0, + "inputParameters": "string", + "outputParameters": "string", + "srcInterface": { + "ipv4Addr": "string", + "ipv6Addr": "string", + "fqdn": "string", + "port": 65535, + "apiPrefix": "string", + "securityMethods": [ + "PSK", + "Oauth" + ] + }, + "destInterface": { + "ipv4Addr": "string", + "ipv6Addr": "string", + "fqdn": "string", + "port": 65535, + "apiPrefix": "string", + "securityMethods": [ + "PSK", + "string" + ] + }, + "fwdInterface": "string" + } + ], + "supportedFeatures": "string" + } + \ No newline at end of file diff --git a/docs/test_plan/api_provider_management/README.md b/docs/test_plan/api_provider_management/README.md new file mode 100644 index 0000000..547d654 --- /dev/null +++ b/docs/test_plan/api_provider_management/README.md @@ -0,0 +1,398 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Provider Management](#test-plan-for-capif-api-provider-management) +- [Tests](#tests) + - [Test Case 1: Register Api Provider](#test-case-1-register-api-provider) + - [Test Case 2: Register Api Provider Already registered](#test-case-2-register-api-provider-already-registered) + - [Test Case 3: Update Registered Api Provider](#test-case-3-update-registered-api-provider) + - [Test Case 4: Update Not Registered Api Provider](#test-case-4-update-not-registered-api-provider) + - [Test Case 5: Partially Update Registered Api Provider](#test-case-5-partially-update-registered-api-provider) + - [Test Case 6: Partially Update Not Registered Api Provider](#test-case-6-partially-update-not-registered-api-provider) + - [Test Case 7: Delete Registered Api Provider](#test-case-7-delete-registered-api-provider) + - [Test Case 8: Delete Not Registered Api Provider](#test-case-8-delete-not-registered-api-provider) + + +# Test Plan for CAPIF Api Provider Management +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Register Api Provider +* **Test ID**: ***capif_api_provider_management-1*** +* **Description**: + + This test case will check that Api Provider can be registered con CCF +* **Pre-Conditions**: + + * Provider is pre-authorised (has valid certificate from CAPIF Authority) + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Store each cert in a file with according name. + +* **Execution Steps**: + + 1. Create private and public key for provider and each function to register. + 2. Register Provider. + +* **Expected Result**: + + 1. Register Provider at Provider Management: + 1. **201 Created** response. + 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. + 3. For each **apiProvFuncs**, we must check: + 1. **apiProvFuncId** is set + 2. **apiProvCert** under **regInfo** is set properly + 5. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* + +## Test Case 2: Register Api Provider Already registered +* **Test ID**: ***capif_api_provider_management-2*** +* **Description**: + + This test case will check that a Api Provider previously registered cannot be re-registered +* **Pre-Conditions**: + + * Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Store each cert in a file with according name. + + 5. Re-Register Provider: + * Same regSec than Previous registration + +* **Execution Steps**: + + 1. Create private and public key for provider and each function to register. + 2. Register Provider. + 3. Re-Register Provider. + +* **Expected Result**: + + 1. Re-Register Provider: + 1. **403 Forbidden** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status 403 + * title with message "Forbidden" + * detail with message "Provider already registered". + * cause with message "Identical provider reg sec". + +## Test Case 3: Update Registered Api Provider +* **Test ID**: ***capif_api_provider_management-3*** +* **Description**: + + This test case will check that a Registered Api Provider can be updated +* **Pre-Conditions**: + + * Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Get Resource URL from Location + + 5. Update Provider: + * Send PUT to Resource URL returned at registration *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}* + * body [provider request body] with apiProvDomInfo set to ROBOT_TESTING_MOD + * Use AMF Certificate. + + +* **Execution Steps**: + + 1. Create private and public key for provider and each function to register. + 2. Register Provider + 3. Update Provider + +* **Expected Result**: + 1. Register Provider: + 1. **201 Created** response. + 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. + 3. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* + + + 2. Update Provider: + 1. **200 OK** response. + 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure, with: + * apiProvDomInfo set to ROBOT_TESTING_MOD + + +## Test Case 4: Update Not Registered Api Provider +* **Test ID**: ***capif_api_provider_management-4*** +* **Description**: + + This test case will check that a Non-Registered Api Provider cannot be updated +* **Pre-Conditions**: + + * Api Provider was not registered previously + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Store each cert in a file with according name. + + 5. Update Not Registered Provider: + * Send PUT *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}* + * body [provider request body] + * Use AMF Certificate. + +* **Execution Steps**: + + 1. Register Provider at CCF + 3. Update Not Registered Provider + +* **Expected Result**: + + 1. Update Not Registered Provider: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status 404 + * title with message "Not Found" + * detail with message "Not Exist Provider Enrolment Details". + * cause with message "Not found registrations to send this api provider details". + +## Test Case 5: Partially Update Registered Api Provider +* **Test ID**: ***capif_api_provider_management-5*** +* **Description**: + + This test case will check that a Registered Api Provider can be partially updated +* **Pre-Conditions**: + + * Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Store each cert in a file with according name. + + 5. Partial update provider: + * Send PATCH *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}* + * body [provider request patch body] + * Use AMF Certificate. + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Register Provider + 3. Partial update provider + +* **Expected Result**: + + 1. Partial update provider at Provider Management: + 1. **200 OK** response. + 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure, with: + * apiProvDomInfo with "ROBOT_TESTING_MOD" + +## Test Case 6: Partially Update Not Registered Api Provider +* **Test ID**: ***capif_api_provider_management-6*** +* **Description**: + + This test case will check that a Non-Registered Api Provider cannot be partially updated + +* **Pre-Conditions**: + + * Api Provider was not registered previously + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Store each cert in a file with according name. + + 5. Partial update Provider: + * Send PATCH *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_API_PROVIDER_NOT_REGISTERED}* + * body [provider request patch body] + * Use AMF Certificate. + + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Register Provider + 3. Partial update provider + +* **Expected Result**: + + 1. Partial update provider: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status 404 + * title with message "Not Found" + * detail with message "Not Exist Provider Enrolment Details". + * cause with message "Not found registrations to send this api provider details". + +## Test Case 7: Delete Registered Api Provider +* **Test ID**: ***capif_api_provider_management-7*** +* **Description**: + + This test case will check that a Registered Api Provider can be deleted +* **Pre-Conditions**: + + * Api Provider was registered previously + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Store each cert in a file with according name. + + 5. Delete registered provider: + * Send DELETE *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}* + * Use AMF Certificate. + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Register Provider + 3. Delete Provider + +* **Expected Result**: + + 1. Delete Provider: + 1. **204 No Content** response. + +## Test Case 8: Delete Not Registered Api Provider +* **Test ID**: ***capif_api_provider_management-8*** +* **Description**: + + This test case will check that a Non-Registered Api Provider cannot be deleted +* **Pre-Conditions**: + + * Api Provider was not registered previously + +* **Information of Test**: + + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Authentication Bearer with access_token + * Store each cert in a file with according name. + + 5. Delete registered provider at Provider Management: + * Send DELETE *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}* + * Use AMF Certificate. + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Delete Provider + +* **Expected Result**: + + 1. Delete Provider: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status 404 + * title with message "Not Found" + * detail with message "Not Exist Provider Enrolment Details". + * cause with message "Not found registrations to send this api provider details". + +[provider register body]: ./provider_details_post_example.json "API Provider Enrolment Request" + +[provider request body]: ./provider_details_post_example.json "API Provider Enrolment Request" + +[provider request patch body]: ./provider_details_enrolment_details_patch_example.json "API Provider Enrolment Patch Request" + +[provider getauth body]: ./provider_getauth_example.json "Get Auth Example" + +[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_provider_management/provider_details_enrolment_details_patch_example.json b/docs/test_plan/api_provider_management/provider_details_enrolment_details_patch_example.json new file mode 100644 index 0000000..4dac4f4 --- /dev/null +++ b/docs/test_plan/api_provider_management/provider_details_enrolment_details_patch_example.json @@ -0,0 +1,29 @@ +{ + "regSec": "", + "apiProvFuncs": [ + { + "regInfo": { + "apiProvPubKey": "" + }, + "apiProvFuncRole": "APF", + "apiProvFuncInfo": "APF_ROBOT_TESTING_PROVIDER" + }, + { + "regInfo": { + "apiProvPubKey": "" + }, + "apiProvFuncRole": "AEF", + "apiProvFuncInfo": "AEF_ROBOT_TESTING_PROVIDER" + }, + { + "regInfo": { + "apiProvPubKey": "" + }, + "apiProvFuncRole": "AMF", + "apiProvFuncInfo": "AMF_ROBOT_TESTING_PROVIDER" + } + ], + "apiProvDomInfo": "ROBOT_TESTING", + "suppFeat": "string", + "failReason": "string" +} \ No newline at end of file diff --git a/docs/test_plan/api_provider_management/provider_details_post_example.json b/docs/test_plan/api_provider_management/provider_details_post_example.json new file mode 100644 index 0000000..48e91ba --- /dev/null +++ b/docs/test_plan/api_provider_management/provider_details_post_example.json @@ -0,0 +1,17 @@ +{ + "regSec": "string", + "apiProvFuncs": [ + { + "apiProvFuncId": "string", + "regInfo": { + "apiProvPubKey": "string", + "apiProvCert": "string" + }, + "apiProvFuncRole": "AEF", + "apiProvFuncInfo": "string" + } + ], + "apiProvDomInfo": "string", + "suppFeat": "string", + "failReason": "string" +} \ No newline at end of file diff --git a/docs/test_plan/api_provider_management/provider_getauth_example.json b/docs/test_plan/api_provider_management/provider_getauth_example.json new file mode 100644 index 0000000..8fc82ae --- /dev/null +++ b/docs/test_plan/api_provider_management/provider_getauth_example.json @@ -0,0 +1,4 @@ +{ + "username": "ROBOT_TESTING_PROVIDER", + "password": "password" +} diff --git a/docs/test_plan/api_provider_management/provider_register_body.json b/docs/test_plan/api_provider_management/provider_register_body.json new file mode 100644 index 0000000..fc26db2 --- /dev/null +++ b/docs/test_plan/api_provider_management/provider_register_body.json @@ -0,0 +1,7 @@ +{ + "password": "password", + "username": "ROBOT_TESTING_PUBLISHER", + "role": "provider", + "description": "Testing", + "cn": "ROBOT_TESTING_PUBLISHER" +} diff --git a/docs/test_plan/api_publish_service/README.md b/docs/test_plan/api_publish_service/README.md new file mode 100644 index 0000000..8487f5d --- /dev/null +++ b/docs/test_plan/api_publish_service/README.md @@ -0,0 +1,599 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Publish Service](#test-plan-for-capif-api-publish-service) +- [Tests](#tests) + - [Test Case 1: Publish API by Authorised API Publisher](#test-case-1-publish-api-by-authorised-api-publisher) + - [Test Case 2: Publish API by NON Authorised API Publisher](#test-case-2-publish-api-by-non-authorised-api-publisher) + - [Test Case 3: Retrieve all APIs Published by Authorised apfId](#test-case-3-retrieve-all-apis-published-by-authorised-apfid) + - [Test Case 4: Retrieve all APIs Published by NON Authorised apfId](#test-case-4-retrieve-all-apis-published-by-non-authorised-apfid) + - [Test Case 5: Retrieve single APIs Published by Authorised apfId](#test-case-5-retrieve-single-apis-published-by-authorised-apfid) + - [Test Case 6: Retrieve single APIs non Published by Authorised apfId](#test-case-6-retrieve-single-apis-non-published-by-authorised-apfid) + - [Test Case 7: Retrieve single APIs Published by NON Authorised apfId](#test-case-7-retrieve-single-apis-published-by-non-authorised-apfid) + - [Test Case 8: Update API Published by Authorised apfId with valid serviceApiId](#test-case-8-update-api-published-by-authorised-apfid-with-valid-serviceapiid) + - [Test Case 9: Update APIs Published by Authorised apfId with invalid serviceApiId](#test-case-9-update-apis-published-by-authorised-apfid-with-invalid-serviceapiid) + - [Test Case 10: Update APIs Published by NON Authorised apfId](#test-case-10-update-apis-published-by-non-authorised-apfid) + - [Test Case 11: Delete API Published by Authorised apfId with valid serviceApiId](#test-case-11-delete-api-published-by-authorised-apfid-with-valid-serviceapiid) + - [Test Case 12: Delete APIs Published by Authorised apfId with invalid serviceApiId](#test-case-12-delete-apis-published-by-authorised-apfid-with-invalid-serviceapiid) + - [Test Case 13: Delete APIs Published by NON Authorised apfId](#test-case-13-delete-apis-published-by-non-authorised-apfid) + + +# Test Plan for CAPIF Api Publish Service +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Publish API by Authorised API Publisher +* **Test ID**: ***capif_api_publish_service-1*** +* **Description**: + + This test case will check that an API Publisher can Publish an API +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API + 3. Retrieve {apiId} from body and Location header with new resource created from response + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Published Service API is stored in CAPIF Database + +## Test Case 2: Publish API by NON Authorised API Publisher +* **Test ID**: ***capif_api_publish_service-2*** +* **Description**: + + This test case will check that an API Publisher cannot Publish an API withot valid apfId +* **Pre-Conditions**: + + * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Publish Service API with invalid APF ID at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis* + * body [service api description] with apiName service_1 + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API with invalid APF ID + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status **401** + * title with message "Unauthorized" + * detail with message "Publisher not existing". + * cause with message "Publisher id not found". + + 2. Service API is NOT stored in CAPIF Database + + +## Test Case 3: Retrieve all APIs Published by Authorised apfId +* **Test ID**: ***capif_api_publish_service-3*** +* **Description**: + + This test case will check that an API Publisher can Retrieve all API published +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) + * At least 2 service APIs are published. + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * Use APF Certificate + + 3. Publish Other Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_2 + * Get apiId + * Use APF Certificate + + 4. Retrieve all published APIs: + * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API service_1 + 3. Retrieve {apiId1} from body and Location header with new resource created from response + 4. Publish Service API service_2 + 5. Retrieve {apiId2} from body and Location header with new resource created from response + 6. Retrieve All published APIs and check if both are present. + +* **Expected Result**: + 1. Response to service 1 Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}* + + 2. Response to service 2 Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}* + + 3. Published Service APIs are stored in CAPIF Database + + 4. Response to Retrieve all published APIs: + 1. **200 OK** + 2. Response body must return an array of **ServiceAPIDescription** data. + 3. Array must contain all previously published APIs. + +## Test Case 4: Retrieve all APIs Published by NON Authorised apfId +* **Test ID**: ***capif_api_publish_service-4*** +* **Description**: + + This test case will check that an API Publisher cannot Retrieve API published when apfId is not authorised +* **Pre-Conditions**: + + * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Retrieve all published APIs: + * Send Get to *https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis* + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Retrieve All published APIs + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **401 Non Authorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status **401** + * title with message "Unauthorized" + * detail with message "Provider not existing". + * cause with message "Provider id not found". + + 2. Service API is NOT stored in CAPIF Database + +## Test Case 5: Retrieve single APIs Published by Authorised apfId +* **Test ID**: ***capif_api_publish_service-5*** +* **Description**: + + This test case will check that an API Publisher can Retrieve API published one by one +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) + * At least 2 service APIs are published. + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * Use APF Certificate + + 3. Publish Other Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_2 + * Get apiId + * Use APF Certificate + + 4. Retrieve service_1 published APIs detail: + * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId1}* + * Use APF Certificate + + 5. Retrieve service_2 published APIs detail: + * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId2}* + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API service_1. + 3. Retrieve {apiId1} from body and Location header with new resource created from response. + 4. Publish Service API service_2. + 5. Retrieve {apiId2} from body and Location header with new resource created from response. + 6. Retrieve service_1 API Detail. + 7. Retrieve service_2 API Detail. + +* **Expected Result**: + 1. Response to service 1 Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}* + + 2. Response to service 2 Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}* + + 3. Published Service APIs are stored in CAPIF Database + + 4. Response to Retrieve service_1 published API using apiId1: + 1. **200 OK** + 2. Response body must return a **ServiceAPIDescription** data. + 3. Array must contain same information than service_1 published registration response. + + 5. Response to Retrieve service_2 published API using apiId2: + 1. **200 OK** + 2. Response body must return a **ServiceAPIDescription** data. + 3. Array must contain same information than service_2 published registration response. + + +## Test Case 6: Retrieve single APIs non Published by Authorised apfId +* **Test ID**: ***capif_api_publish_service-6*** +* **Description**: + + This test case will check that an API Publisher try to get detail of not published api. +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) + * No published api + +* **Information of Test**: + 1. Perform [Provider Registration] + 2. Retrieve not published APIs detail: + * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Retrieve not published API Detail. + +* **Expected Result**: + 1. Response to Retrieve for NOT published API must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status **404** + * title with message "Not Found" + * detail with message "Service API not found". + * cause with message "No Service with specific credentials exists". + + +## Test Case 7: Retrieve single APIs Published by NON Authorised apfId +* **Test ID**: ***capif_api_publish_service-7*** +* **Description**: + + This test case will check that an API Publisher cannot Retrieve detailed API published when apfId is not authorised +* **Pre-Conditions**: + + * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * Use APF Certificate + + 3. Retrieve detailed published APIs: + * Send Get to *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/${apiId}* + * Use Invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API at CCF + 3. Retrieve {apiId} from body and Location header with new resource created from response. + 4. Register and onboard Invoker at CCF + 5. Store signed Invoker Certificate + 6. Retrieve detailed published API acting as Invoker + +* **Expected Result**: + 1. Response to Retrieve Detailed published API acting as Invoker must accomplish: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status **401** + * title with message "Unauthorized" + * detail with message "User not authorized". + * cause with message "Certificate not authorized". + + 2. Service API is NOT stored in CAPIF Database + + +## Test Case 8: Update API Published by Authorised apfId with valid serviceApiId +* **Test ID**: ***capif_api_publish_service-8*** +* **Description**: + + This test case will check that an API Publisher can Update published API with a valid serviceApiId +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) + * A service APIs is published. + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * get resource url from location Header. + * Use APF Certificate + + 3. Update published API at CCF: + * Send PUT to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* + * body [service api description] with overrided apiName to service_1_modified + * Use APF Certificate + + 4. Retrieve detail of service API: + * Send Get to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* + * check apiName is service_1_modified + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API + 3. Retrieve {apiId} from body and Location header with new resource url created from response + 4. Update published Service API. + 5. Retrieve detail of Service API + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Response to Update Published Service API: + 1. **200 OK** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiName service_1_modified + + 3. Response to Retrieve detail of Service API: + 1. **200 OK** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiName service_1_modified. + + +## Test Case 9: Update APIs Published by Authorised apfId with invalid serviceApiId +* **Test ID**: ***capif_api_publish_service-9*** +* **Description**: + + This test case will check that an API Publisher cannot Update published API with a invalid serviceApiId +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * Use APF Certificate + + 3. Update published API at CCF: + * Send PUT to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* + * body [service api description] with overrided apiName to ***service_1_modified*** + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Update published Service API. + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Response to Update Published Service API: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status **404** + * title with message "Not Found" + * detail with message "Service API not found". + * cause with message "Service API id not found". + + ## Test Case 10: Update APIs Published by NON Authorised apfId +* **Test ID**: ***capif_api_publish_service-10*** +* **Description**: + + This test case will check that an API Publisher cannot Update API published when apfId is not authorised +* **Pre-Conditions**: + + * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * Use APF Certificate + + 3. Update published API at CCF: + * Send PUT to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + * body [service api description] with overrided apiName to ***service_1_modified*** + * Use invoker certificate + + 4. Retrieve detail of service API: + * Send Get to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* + * check apiName is service_1 + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API at CCF + 3. Retrieve {apiId} from body and Location header with new resource created from response. + 4. Register and onboard Invoker at CCF + 5. Store signed Invoker Certificate + 6. Update published API at CCF as Invoker + 7. Retrieve detail of Service API as publisher + +* **Expected Result**: + 1. Response to Update published API acting as Invoker must accomplish: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status **401** + * title with message "Unauthorized" + * detail with message "User not authorized". + * cause with message "Certificate not authorized". + + 2. Response to Retrieve Detail of Service API: + 1. **200 OK** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiName service_1. + + +## Test Case 11: Delete API Published by Authorised apfId with valid serviceApiId +* **Test ID**: ***capif_api_publish_service-11*** +* **Description**: + + This test case will check that an API Publisher can Delete published API with a valid serviceApiId +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority). + * A service APIs is published. + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * Use APF Certificate + + 3. Remove published Service API at CCF: + * Send DELETE to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + * Use APF Certificate + 4. Retrieve detail of service API: + * Send Get to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Publish Service API + 3. Retrieve {apiId} from body and Location header with new resource created from response + 4. Remove published API at CCF + 5. Try to retreive deleted service API from CCF + +* **Expected Result**: + 1. Response to Publish request must accomplish: + 1. **201 Created** + 2. Response Body must follow **ServiceAPIDescription** data structure with: + * apiId + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* + + 2. Published Service API is stored in CAPIF Database + + 3. Response to Remove published Service API at CCF: + 1. **204 No Content** + + 4. Response to Retrieve for DELETED published API must accomplish: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Service API not found". + * cause with message "No Service with specific credentials exists". + + +## Test Case 12: Delete APIs Published by Authorised apfId with invalid serviceApiId +* **Test ID**: ***capif_api_publish_service-12*** +* **Description**: + + This test case will check that an API Publisher cannot Delete with invalid serviceApiId +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority). + +* **Information of Test**: + 1. Perform [Provider Registration] + + 2. Remove published Service API at CCF with invalid serviceId: + * Send DELETE to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* + * Use APF Certificate + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Remove published API at CCF with invalid serviceId + +* **Expected Result**: + 1. Response to Remove published Service API at CCF: + 1. **404 Not Found** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status 404 + * title with message "Not Found" + * detail with message "Service API not found". + * cause with message "Service API id not found". + + +## Test Case 13: Delete APIs Published by NON Authorised apfId +* **Test ID**: ***capif_api_publish_service-12*** +* **Description**: + + This test case will check that an API Publisher cannot Delete API published when apfId is not authorised +* **Pre-Conditions**: + + * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority). + +* **Information of Test**: + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* + * body [service api description] with apiName service_1 + * Get apiId + * Use APF Certificate + + 3. Remove published Service API at CCF with invalid serviceId as Invoker: + * Send DELETE to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* + * Use invoker certificate. + +* **Execution Steps**: + 1. Register Provider at CCF and store certificates. + 2. Register Invoker and onboard Invoker at CCF + 3. Remove published API at CCF with invalid serviceId as Invoker + +* **Expected Result**: + 1. Response to Remove published Service API at CCF: + 1. **401 Unauthorized** + 2. Error Response Body must accomplish with **ProblemDetails** data structure with: + * status **401** + * title with message "Unauthorized" + * detail with message "User not authorized". + * cause with message "Certificate not authorized". + + + [service api description]: ./service_api_description_post_example.json "Service API Description Request" + [publisher register body]: ./publisher_register_body.json "Publish register Body" + [invoker onboarding body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" + [invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" + [provider request body]: ../api_provider_management/provider_details_post_example.json "API Provider Enrolment Request" + [provider request patch body]: ../api_provider_management/provider_details_enrolment_details_patch_example.json "API Provider Enrolment Patch Request" + [provider getauth body]: ../api_provider_management/provider_getauth_example.json "Get Auth Example" + + [invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" + [provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" + + + [Return To All Test Plans]: ../README.md \ No newline at end of file diff --git a/docs/test_plan/api_publish_service/publisher_register_body.json b/docs/test_plan/api_publish_service/publisher_register_body.json new file mode 100644 index 0000000..fc26db2 --- /dev/null +++ b/docs/test_plan/api_publish_service/publisher_register_body.json @@ -0,0 +1,7 @@ +{ + "password": "password", + "username": "ROBOT_TESTING_PUBLISHER", + "role": "provider", + "description": "Testing", + "cn": "ROBOT_TESTING_PUBLISHER" +} diff --git a/docs/test_plan/api_publish_service/service_api_description_post_example.json b/docs/test_plan/api_publish_service/service_api_description_post_example.json new file mode 100644 index 0000000..b725b42 --- /dev/null +++ b/docs/test_plan/api_publish_service/service_api_description_post_example.json @@ -0,0 +1,113 @@ +{ + "apiName": "service_1", + "aefProfiles": [ + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + }, + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + } + ], + "description": "string", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" +} \ No newline at end of file diff --git a/docs/test_plan/api_security_service/README.md b/docs/test_plan/api_security_service/README.md new file mode 100644 index 0000000..c0d3e71 --- /dev/null +++ b/docs/test_plan/api_security_service/README.md @@ -0,0 +1,1244 @@ +[**[Return To All Test Plans]**] + +- [Test Plan for CAPIF Api Security Service](#test-plan-for-capif-api-security-service) +- [Tests](#tests) + - [Test Case 1: Create a security context for an API invoker](#test-case-1-create-a-security-context-for-an-api-invoker) + - [Test Case 2: Create a security context for an API invoker with Provider role](#test-case-2-create-a-security-context-for-an-api-invoker-with-provider-role) + - [Test Case 3: Create a security context for an API invoker with Provider entity role and invalid apiInvokerId](#test-case-3-create-a-security-context-for-an-api-invoker-with-provider-entity-role-and-invalid-apiinvokerid) + - [Test Case 4: Create a security context for an API invoker with Invoker entity role and invalid apiInvokerId](#test-case-4-create-a-security-context-for-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid) + - [Test Case 5: Retrieve the Security Context of an API Invoker](#test-case-5-retrieve-the-security-context-of-an-api-invoker) + - [Test Case 6: Retrieve the Security Context of an API Invoker with invalid apiInvokerID](#test-case-6-retrieve-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid) + - [Test Case 7: Retrieve the Security Context of an API Invoker with invalid apfId](#test-case-7-retrieve-the-security-context-of-an-api-invoker-with-invalid-apfid) + - [Test Case 8: Delete the Security Context of an API Invoker](#test-case-8-delete-the-security-context-of-an-api-invoker) + - [Test Case 9: Delete the Security Context of an API Invoker with Invoker entity role](#test-case-9-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role) + - [Test Case 10: Delete the Security Context of an API Invoker with Invoker entity role and invalid apiInvokerID](#test-case-10-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid) + - [Test Case 11: Delete the Security Context of an API Invoker with invalid apiInvokerID](#test-case-11-delete-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid) + - [Test Case 12: Update the Security Context of an API Invoker](#test-case-12-update-the-security-context-of-an-api-invoker) + - [Test Case 13: Update the Security Context of an API Invoker with Provider entity role](#test-case-13-update-the-security-context-of-an-api-invoker-with-provider-entity-role) + - [Test Case 14: Update the Security Context of an API Invoker with AEF entity role and invalid apiInvokerId](#test-case-14-update-the-security-context-of-an-api-invoker-with-aef-entity-role-and-invalid-apiinvokerid) + - [Test Case 15: Update the Security Context of an API Invoker with invalid apiInvokerID](#test-case-15-update-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid) + - [Test Case 16: Revoke the authorization of the API invoker for APIs.](#test-case-16-revoke-the-authorization-of-the-api-invoker-for-apis) + - [Test Case 17: Revoke the authorization of the API invoker for APIs without valid apfID.](#test-case-17-revoke-the-authorization-of-the-api-invoker-for-apis-without-valid-apfid) + - [Test Case 18: Revoke the authorization of the API invoker for APIs with invalid apiInvokerId.](#test-case-18-revoke-the-authorization-of-the-api-invoker-for-apis-with-invalid-apiinvokerid) + - [Test Case 19: Retrieve access token](#test-case-19-retrieve-access-token) + - [Test Case 20: Retrieve access token by Provider](#test-case-20-retrieve-access-token-by-provider) + - [Test Case 21: Retrieve access token by Provider with invalid apiInvokerId](#test-case-21-retrieve-access-token-by-provider-with-invalid-apiinvokerid) + - [Test Case 22: Retrieve access token with invalid apiInvokerId](#test-case-22-retrieve-access-token-with-invalid-apiinvokerid) + - [Test Case 23: Retrieve access token with invalid client\_id](#test-case-23-retrieve-access-token-with-invalid-client_id) + - [Test Case 24: Retrieve access token with unsupported grant\_type](#test-case-24-retrieve-access-token-with-unsupported-grant_type) + - [Test Case 25: Retrieve access token with invalid scope](#test-case-25-retrieve-access-token-with-invalid-scope) + - [Test Case 26: Retrieve access token with invalid aefid at scope](#test-case-26-retrieve-access-token-with-invalid-aefid-at-scope) + - [Test Case 27: Retrieve access token with invalid apiName at scope](#test-case-27-retrieve-access-token-with-invalid-apiname-at-scope) + + + +# Test Plan for CAPIF Api Security Service +At this documentation you will have all information and related files and examples of test plan for this API. + +# Tests + +## Test Case 1: Create a security context for an API invoker +* **Test ID**: ***capif_security_api-1*** +* **Description**: + + This test case will check that an API Invoker can create a Security context +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) + +* **Information of Test**: + 1. Perform [Invoker Onboarding] + 2. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Use Invoker Certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Store signed Certificate + 3. Create Security Context + +* **Expected Result**: + + 1. Create security context: + 1. **201 Created** response. + 2. body returned must accomplish **ServiceSecurity** data structure. + 3. Location Header must contain the new resource URL *{apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}* + + +## Test Case 2: Create a security context for an API invoker with Provider role +* **Test ID**: ***capif_security_api-2*** +* **Description**: + + This test case will check that an Provider cannot create a Security context with valid apiInvokerId. +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker but using Provider certificate. + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using AEF certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context using Provider certificate + +* **Expected Result**: + + 1. Create security context using Provider certificate: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be invoker". + + 2. No context stored at DB + +## Test Case 3: Create a security context for an API invoker with Provider entity role and invalid apiInvokerId +* **Test ID**: ***capif_security_api-3*** +* **Description**: + + This test case will check that an Provider cannot create a Security context with invalid apiInvokerID. +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Create Security Context for this not valid apiInvokerId and using Provider certificate. + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* + * body [service security body] + * Using AEF certificate + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Create Security Context using Provider certificate + +* **Expected Result**: + + 1. Create security context using Provider certificate: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be invoker". + 2. No context stored at DB + +## Test Case 4: Create a security context for an API invoker with Invoker entity role and invalid apiInvokerId +* **Test ID**: ***capif_security_api-4*** +* **Description**: + + This test case will check that an Invoker cannot create a Security context with valid apiInvokerId. +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with invalid apiInvokerId + +* **Information of Test**: + 1. Perform [Invoker Onboarding] + + 2. Create Security Context for this Invoker: + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* + * body [service security body] + * Use Invoker Certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Create Security Context using Provider certificate + +* **Expected Result**: + + 1. Create security context using Provider certificate: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **404** + * title with message "Not Found" + * detail with message "Invoker not found". + * cause with message "API Invoker not exists or invalid ID". + + 2. No context stored at DB + + +## Test Case 5: Retrieve the Security Context of an API Invoker +* **Test ID**: ***capif_security_api-5*** +* **Description**: + + This test case will check that an provider can retrieve the Security context of an API Invoker +* **Pre-Conditions**: + + * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker. + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker certificate + + 3. Retrieve Security Context of Invoker by Provider: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Using AEF Certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context using Provider certificate + 4. Retrieve Security Context by Provider + +* **Expected Result**: + 1. Retrieve security context: + 1. **200 OK** response. + 2. body returned must accomplish **ServiceSecurity** data structure. + + +## Test Case 6: Retrieve the Security Context of an API Invoker with invalid apiInvokerID +* **Test ID**: ***capif_security_api-6*** +* **Description**: + + This test case will check that an provider can retrieve the Security context of an API Invoker +* **Pre-Conditions**: + + * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Retrieve Security Context of invalid Invoker by Provider: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* + * Using AEF Certificate. + +* **Execution Steps**: + + 2. Register Provider at CCF + 3. Create Security Context using Provider certificate + 4. Retrieve Security Context by Provider of invalid invoker + +* **Expected Result**: + 1. Retrieve security context: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **404** + * title with message "Not Found" + * detail with message "Invoker not found". + * cause with message "API Invoker not exists or invalid ID". + + +## Test Case 7: Retrieve the Security Context of an API Invoker with invalid apfId +* **Test ID**: ***capif_security_api-7*** +* **Description**: + + This test case will check that an Provider cannot retrieve the Security context of an API Invoker without valid apfId +* **Pre-Conditions**: + + * API Exposure Function is not pre-authorised (has invalid apfId) + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate + + 3. Retrieve Security Context as Invoker role: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Using Invoker Certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Store signed Certificate + 3. Create Security Context + 4. Retrieve Security Context as Provider. + +* **Expected Result**: + + 1. Create security context: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be aef". + + +## Test Case 8: Delete the Security Context of an API Invoker +* **Test ID**: ***capif_security_api-8*** +* **Description**: + + This test case will check that an Provider can delete a Security context +* **Pre-Conditions**: + + * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker but using Provider certificate. + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using AEF certificate + + 3. Delete Security Context of Invoker by Provider: + * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Use AEF certificate + + 4. Retrieve Security Context of Invoker by Provider: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Using AEF Certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context using Provider certificate + 4. Delete Security Context by Provider + +* **Expected Result**: + + 1. Delete security context: + 1. **204 No Content** response. + + 2. Retrieve security context: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **404** + * title with message "Not Found" + * detail with message "Security context not found". + * cause with message "API Invoker not exists or invalid ID". + + +## Test Case 9: Delete the Security Context of an API Invoker with Invoker entity role +* **Test ID**: ***capif_security_api-9*** +* **Description**: + + This test case will check that an Invoker cannot delete a Security context +* **Pre-Conditions**: + + * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker: + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker certificate + + 3. Delete Security Context of Invoker: + * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Use Invoker certificate + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Create Security Context using Provider certificate + 3. Delete Security Context by Invoker + +* **Expected Result**: + + 1. Delete security context: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be aef". + + +## Test Case 10: Delete the Security Context of an API Invoker with Invoker entity role and invalid apiInvokerID +* **Test ID**: ***capif_security_api-10*** +* **Description**: + + This test case will check that an Invoker cannot delete a Security context with invalid +* **Pre-Conditions**: + + * Invoker is pre-authorised. + +* **Information of Test**: + + 1. Perform [Invoker Onboarding] + + 2. Delete Security Context of Invoker: + * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* + * Use Invoker certificate + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Delete Security Context by invoker + +* **Expected Result**: + + 1. Delete security context: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be aef". + + +## Test Case 11: Delete the Security Context of an API Invoker with invalid apiInvokerID +* **Test ID**: ***capif_security_api-11*** +* **Description**: + + This test case will check that an Provider cannot delete a Security context of invalid apiInvokerId +* **Pre-Conditions**: + + * Provider is pre-authorised (has valid apfId from CAPIF Authority). + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 2. Delete Security Context of Invoker by Provider: + * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* + * Use AEF certificate + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Delete Security Context by provider + +* **Expected Result**: + + 1. Retrieve security context: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **404** + * title with message "Not Found" + * detail with message "Invoker not found". + * cause with message "API Invoker not exists or invalid ID". + + +## Test Case 12: Update the Security Context of an API Invoker +* **Test ID**: ***capif_security_api-12*** +* **Description**: + + This test case will check that an API Invoker can update a Security context +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker: + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + + 3. Update Security Context of Invoker: + * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update* + * body [service security body] but with notification destination modified to http://robot.testing2 + * Using Invoker Certificate. + + 4. Retrieve Security Context of Invoker by Provider: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Using AEF Certificate. + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context By Invoker + 4. Update Security Context By Invoker + 5. Retrieve Security Context By Provider + +* **Expected Result**: + + 1. Update security context: + 1. **200 OK** response. + 2. body returned must accomplish **ServiceSecurity** data structure. + + 2. Retrieve security context: + 1. **200 OK** response. + 2. body returned must accomplish **ServiceSecurity** data structure. + 1. Check is this returned object match with modified one. + + +## Test Case 13: Update the Security Context of an API Invoker with Provider entity role +* **Test ID**: ***capif_security_api-13*** +* **Description**: + + This test case will check that an Provider cannot update a Security context + +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized. + * Invoker has created the Security Context previously. + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker: + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + + 3. Update Security Context of Invoker by Provider: + * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update* + * body [service security body] but with notification destination modified to http://robot.testing2 + * Using AEF Certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context + 4. Update Security Context as Provider + +* **Expected Result**: + + 1. Update security context: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be invoker". + + +## Test Case 14: Update the Security Context of an API Invoker with AEF entity role and invalid apiInvokerId +* **Test ID**: ***capif_security_api-14*** +* **Description**: + + This test case will check that an Provider cannot update a Security context of invalid apiInvokerId + +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized. + * Invoker has created the Security Context previously. + +* **Information of Test**: + + 1. Perform [Provider Registration] + + 4. Update Security Context of Invoker by Provider: + * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update* + * body [service security body] + * Using AEF Certificate + +* **Execution Steps**: + + 1. Register Provider at CCF + 2. Update Security Context as Provider + +* **Expected Result**: + + 1. Update security context: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be invoker". + + +## Test Case 15: Update the Security Context of an API Invoker with invalid apiInvokerID +* **Test ID**: ***capif_security_api-15*** +* **Description**: + + This test case will check that an API Invoker cannot update a Security context not valid apiInvokerId +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Update Security Context of Invoker: + * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update* + * body [service security body] + * Using Invoker Certificate. + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Update Security Context + +* **Expected Result**: + +1. Retrieve security context: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **404** + * title with message "Not Found" + * detail with message "Invoker not found". + * cause with message "API Invoker not exists or invalid ID". + + +## Test Case 16: Revoke the authorization of the API invoker for APIs. +* **Test ID**: ***capif_security_api-16*** +* **Description**: + + This test case will check that a Provider can revoke the authorization for APIs + +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context By Invoker: + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate + + 3. Revoke Authorization by Provider: + * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete* + * body [security notification body] + * Using AEF Certificate. + + 4. Retrieve Security Context by Provider: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Using AEF Certificate. + + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context by Invoker + 4. Revoke Security Context by Provider + 5. Retrieve Security Context by Provider + +* **Expected Result**: + + 1. Revoke Authorization: + 1. **204 No Content** response. + + 2. Retrieve security context: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **404** + * title with message "Not Found" + * detail with message "Security context not found". + * cause with message "API Invoker has no security context". + + +## Test Case 17: Revoke the authorization of the API invoker for APIs without valid apfID. +* **Test ID**: ***capif_security_api-17*** +* **Description**: + + This test case will check that an Invoker can't revoke the authorization for APIs + +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker: + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + + 3. Revoke Authorization by invoker: + * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete* + * body [security notification body] + * Using Invoker Certificate + + 4. Retrieve Security Context of Invoker by Provider: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * Using Provider Certificate + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context + 4. Revoke Security Context by invoker + 5. Retrieve Security Context + +* **Expected Result**: + + 1. Revoke Security Context by invoker: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **401** + * title with message "Unauthorized" + * detail with message "Role not authorized for this API route". + * cause with message "User role must be provider". + + 3. Retrieve security context: + 1. **200 OK** response. + 2. body returned must accomplish **ServiceSecurity** data structure. + 1. Check is this returned object match with created one. + + +## Test Case 18: Revoke the authorization of the API invoker for APIs with invalid apiInvokerId. +* **Test ID**: ***capif_security_api-18*** +* **Description**: + + This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId + +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Create Security Context for this Invoker: + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + + 3. Revoke Authorization by Provider: + * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/delete* + * body [security notification body] + * Using AEF Certificate. + + 4. Retrieve Security Context of Invoker by Provider: + * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}?authenticationInfo=true&authorizationInfo=true* + * This request will ask with parameter to retrieve authenticationInfo and authorizationInfo + * Using AEF Certificate. + +* **Execution Steps**: + + 1. Register and onboard Invoker at CCF + 2. Register Provider at CCF + 3. Create Security Context + 4. Revoke Security Context by Provider + 5. Retrieve Security Context + +* **Expected Result**: + + 1. Revoke Security Context by invoker: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails** data structure, with: + * status **404** + * title with message "Not Found" + * detail with message "Invoker not found". + * cause with message "API Invoker not exists or invalid ID". + + 3. Retrieve security context: + 1. **200 OK** response. + 2. body returned must accomplish **ServiceSecurity** data structure. + 1. Check is this return one object that match with created one. + + +## Test Case 19: Retrieve access token +* **Test ID**: ***capif_security_api-19*** +* **Description**: + + This test case will check that an API Invoker can retrieve a security access token OAuth 2.0. +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerId) + * Service API of Provider is published + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by invoker: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*: + * body [access token req body] and example [example] + * ***securityId*** is apiInvokerId. + * ***grant_type=client_credentials***. + * Create Scope properly for request: ***3gpp#{aef_id}:{api_name}*** + * Using Invoker Certificate. + +* **Execution Steps**: + + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **200 OK** + 2. body must follow **AccessTokenRsp** with: + 1. access_token present + 2. token_type=Bearer + +## Test Case 20: Retrieve access token by Provider +* **Test ID**: ***capif_security_api-20*** +* **Description**: + + This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId + +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by provider: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*: + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=client_credentials*** + * Using AEF certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Provider + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **AccessTokenErr** data structure, with: + * error unauthorized_client + * error_description=Role not authorized for this API route + +## Test Case 21: Retrieve access token by Provider with invalid apiInvokerId +* **Test ID**: ***capif_security_api-21*** +* **Description**: + + This test case will check that an API Exposure Function cannot retrieve a security access token without valid apiInvokerId + +* **Pre-Conditions**: + + * API Invoker is pre-authorised and Provider is also authorized + + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by provider: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token*. + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=client_credentials*** + * Using AEF certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Provider + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **401 Unauthorized** response. + 2. body returned must accomplish **AccessTokenErr** data structure, with: + * error unauthorized_client + * error_description=Role not authorized for this API route + + +## Test Case 22: Retrieve access token with invalid apiInvokerId +* **Test ID**: ***capif_security_api-22*** +* **Description**: + + This test case will check that an API Invoker can't retrieve a security access token without valid apiInvokerId + +* **Pre-Conditions**: + + * API Invoker is pre-authorised (has valid apiInvokerId) + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + 5. Request Access Token by invoker: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token*. + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=client_credentials*** + * Using Invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Invoker + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **404 Not Found** response. + 2. body returned must accomplish **ProblemDetails29571** data structure, with: + * status 404 + * title Not Found + * detail Security context not found + * cause API Invoker has no security context + + +**NOTE: ProblemDetails29571 is the definition present for this request at swagger of ProblemDetails, and this is different from definition of ProblemDetails across other CAPIF Services** + +## Test Case 23: Retrieve access token with invalid client_id +* **Test ID**: ***capif_security_api-23*** +* **Description**: + + This test case will check that an API Exposure Function cannot retrieve a security access token without valid client_id at body + +* **Pre-Conditions**: + + * API Invoker is pre-authorised and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by invoker: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=client_credentials*** + * **client_id is not-valid** + * Using Invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Invoker + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **400 Bad Request** response. + 2. body returned must accomplish **AccessTokenErr** data structure, with: + * error invalid_client + * error_description=Client Id not found + + +## Test Case 24: Retrieve access token with unsupported grant_type +* **Test ID**: ***capif_security_api-24*** +* **Description**: + + This test case will check that an API Exposure Function cannot retrieve a security access token with unsupported grant_type + +* **Pre-Conditions**: + + * API Invoker is pre-authorised and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by invoker: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=not_valid*** + * Using Invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Invoker + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **400 Bad Request** response. + 2. body returned must accomplish **AccessTokenErr** data structure, with: + * error unsupported_grant_type + * error_description=Invalid value for `grant_type` \\(${grant_type}\\), must be one of \\['client_credentials'\\] - 'grant_type' + +## Test Case 25: Retrieve access token with invalid scope +* **Test ID**: ***capif_security_api-25*** +* **Description**: + + This test case will check that an API Exposure Function cannot retrieve a security access token with complete invalid scope + +* **Pre-Conditions**: + + * API Invoker is pre-authorised and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by invoker: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=client_credentials*** + * ***scope=not-valid-scope*** + * Using Invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Invoker + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **400 Bad Request** response. + 2. body returned must accomplish **AccessTokenErr** data structure, with: + * error invalid_scope + * error_description=The first characters must be '3gpp' + + +## Test Case 26: Retrieve access token with invalid aefid at scope +* **Test ID**: ***capif_security_api-26*** +* **Description**: + + This test case will check that an API Exposure Function cannot retrieve a security access token with invalid aefId at scope + +* **Pre-Conditions**: + + * API Invoker is pre-authorised and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by invoker: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=client_credentials*** + * ***scope=3gpp#1234:service_1*** + * Using Invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Invoker + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **400 Bad Request** response. + 2. body returned must accomplish **AccessTokenErr** data structure, with: + * error invalid_scope + * error_description=One of aef_id not belongs of your security context + + +## Test Case 27: Retrieve access token with invalid apiName at scope +* **Test ID**: ***capif_security_api-27*** +* **Description**: + + This test case will check that an API Exposure Function cannot retrieve a security access token with invalid apiName at scope + +* **Pre-Conditions**: + + * API Invoker is pre-authorised and Provider is also authorized + +* **Information of Test**: + + 1. Perform [Provider Registration] and [Invoker Onboarding] + + 2. Publish Service API at CCF: + * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis + * body [service api description] with apiName service_1 + * Use APF Certificate + + 3. Request Discover Published APIs not filtered: + * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* + * Param api-invoker-id is mandatory + * Using invoker certificate + + 4. Create Security Context for this Invoker + * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* + * body [service security body] + * Using Invoker Certificate. + * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. + + 5. Request Access Token by invoker: + * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. + * body [access token req body] + * ***securityId*** is apiInvokerId + * ***grant_type=client_credentials*** + * ***scope=3gpp#{aef_id}:not-valid*** + * Using Invoker certificate + +* **Execution Steps**: + 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF + 2. Register and onboard Invoker at CCF + 3. Discover Service APIs by Invoker. + 4. Create Security Context According to Service APIs discovered. + 5. Request Access Token by Invoker + +* **Expected Result**: + + 1. Response to Request of Access Token: + 1. **400 Bad Request** response. + 2. body returned must accomplish **AccessTokenErr** data structure, with: + * error invalid_scope + * error_description=One of the api names does not exist or is not associated with the aef id provided + + + [Return To All Test Plans]: ../README.md + + + + [service security body]: ./service_security.json "Service Security Request" + [security notification body]: ./security_notification.json "Security Notification Request" + [access token req body]: ./access_token_req.json "Access Token Request" + [example]: ./access_token_req.json "Access Token Request Example" + + [invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" + [provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" + + diff --git a/docs/test_plan/api_security_service/access_token_req.json b/docs/test_plan/api_security_service/access_token_req.json new file mode 100644 index 0000000..8504736 --- /dev/null +++ b/docs/test_plan/api_security_service/access_token_req.json @@ -0,0 +1,6 @@ +{ + "client_id": "client_id", + "client_secret": "client_secret", + "grant_type": "client_credentials", + "scope": "scope" +} \ No newline at end of file diff --git a/docs/test_plan/api_security_service/access_token_req_example.json b/docs/test_plan/api_security_service/access_token_req_example.json new file mode 100644 index 0000000..070a717 --- /dev/null +++ b/docs/test_plan/api_security_service/access_token_req_example.json @@ -0,0 +1,5 @@ +{ + "client_id": "bb260b4d0b3a0f954fa23f42d979ca", + "grant_type": "client_credentials", + "scope": "3gpp#af7e4cf70063814770e7b00b87273e:service_1" +} diff --git a/docs/test_plan/api_security_service/security_notification.json b/docs/test_plan/api_security_service/security_notification.json new file mode 100644 index 0000000..6b94eb5 --- /dev/null +++ b/docs/test_plan/api_security_service/security_notification.json @@ -0,0 +1,9 @@ +{ + "aefId": "aefId", + "apiIds": [ + "apiIds", + "apiIds" + ], + "apiInvokerId": "api_invoker_id", + "cause": "OVERLIMIT_USAGE" +} \ No newline at end of file diff --git a/docs/test_plan/api_security_service/service_security.json b/docs/test_plan/api_security_service/service_security.json new file mode 100644 index 0000000..ad7bc1a --- /dev/null +++ b/docs/test_plan/api_security_service/service_security.json @@ -0,0 +1,25 @@ +{ + "notificationDestination": "http://robot.testing", + "supportedFeatures": "fffffff", + "securityInfo": [{ + "authenticationInfo": "authenticationInfo", + "authorizationInfo": "authorizationInfo", + "interfaceDetails": { + "ipv4Addr": "127.0.0.1", + "securityMethods": ["PSK"], + "port": 5248 + }, + "prefSecurityMethods": ["PSK", "PKI", "OAUTH"], + }, + { + "authenticationInfo": "authenticationInfo", + "authorizationInfo": "authorizationInfo", + "prefSecurityMethods": ["PSK", "PKI", "OAUTH"], + "aefId": "aefId" + }], + "websockNotifConfig": { + "requestWebsocketUri": true, + "websocketUri": "websocketUri" + }, + "requestTestNotification": true +} diff --git a/docs/test_plan/common_operations/README.md b/docs/test_plan/common_operations/README.md new file mode 100644 index 0000000..ff39d94 --- /dev/null +++ b/docs/test_plan/common_operations/README.md @@ -0,0 +1,86 @@ + +# Register an Invoker + +## Steps to perform operation + 1. Create public and private key at invoker + 2. Register of Invoker at CCF: + * Send POST to http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register + * Body [invoker register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [invoker getauth body] + + 4. Onboard Invoker: + * Send POST to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers + * Reference Request Body: [invoker onboarding body] + * "onboardingInformation"->"apiInvokerPublicKey": must contain public key generated by Invoker. + * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) + +## Checks to ensure onboarding + 1. Response to Register: + 1. **201 Created** + + 2. Response to Get Auth: + 1. **200 OK** + 2. ***access_token*** returned. + + 3. Response to Onboard request must accomplish: + 1. **201 Created** + 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: + * apiInvokerId + * onboardingInformation->apiInvokerCertificate must contain the public key signed. + 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* + + +# Register a Provider + +## Steps to Perform operation + 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) + 2. Register of Provider at CCF: + * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* + * body [provider register body] + + 3. Obtain Access Token: + * Send POST to *http://{CAPIF_HOSTNAME}/getauth* + * Body [provider getauth body] + + 4. Register Provider: + * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* + * body [provider request body] + * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) + * Store each cert in a file with according name. + +## Checks to ensure provider registration + 1. Response to Register: + 1. **201 Created** + + 2. Response to Get Auth: + 1. **200 OK** + 2. ***access_token*** returned. + + 3. Register Provider at Provider Management: + 1. **201 Created** response. + 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. + 3. For each **apiProvFuncs**, we must check: + 1. **apiProvFuncId** is set + 2. **apiProvCert** under **regInfo** is set properly + 4. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* + + + + + +[invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" +[invoker onboarding body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" +[invoker getauth body]: ../api_invoker_management/invoker_getauth_example.json "Get Auth Example" + +[provider register body]: ../api_provider_management/provider_register_body.json "Provider Register Body" +[provider request body]: ../api_provider_management/provider_details_post_example.json "API Provider Enrolment Request" +[provider getauth body]: ../api_provider_management/provider_getauth_example.json "Get Auth Example" + + + + + +[Return To All Test Plans]: ../README.md diff --git a/docs/testing_with_curl/README.md b/docs/testing_with_curl/README.md new file mode 100644 index 0000000..d8c3982 --- /dev/null +++ b/docs/testing_with_curl/README.md @@ -0,0 +1,369 @@ +[**[Return To Main]**] +# Testing Using Curl + +- [Testing Using Curl](#testing-using-curl) + - [cURL scripts (TLS supported)](#curl-scripts-tls-supported) + - [cURL manual execution](#curl-manual-execution) + - [Authentication](#authentication) + - [Invoker](#invoker) + - [Provider](#provider) + - [JWT Authentication APIs](#jwt-authentication-apis) + - [Register an entity](#register-an-entity) + - [Get access token for an existing entity](#get-access-token-for-an-existing-entity) + - [Retrieve and store CA certificate](#retrieve-and-store-ca-certificate) + - [Sign provider certificate](#sign-provider-certificate) + - [Invoker Management APIs](#invoker-management-apis) + - [Onboard an Invoker](#onboard-an-invoker) + - [Update Invoker Details](#update-invoker-details) + - [Offboard an Invoker](#offboard-an-invoker) + - [Publish APIs](#publish-apis) + - [Publish a new API.](#publish-a-new-api) + - [Update a published service API.](#update-a-published-service-api) + - [Unpublish a published service API.](#unpublish-a-published-service-api) + - [Retrieve all published APIs](#retrieve-all-published-apis) + - [Retrieve a published service API.](#retrieve-a-published-service-api) + - [Discover API](#discover-api) + - [Discover published service APIs and retrieve a collection of APIs according to certain filter criteria.](#discover-published-service-apis-and-retrieve-a-collection-of-apis-according-to-certain-filter-criteria) + +## cURL scripts (TLS supported) +Also you can follow the instructions and run the commands of the bash scripts: +* [provider](./capif_tls_curls_exposer.sh) to test CAPIF as provider with TLS support. +* [invoker](./capif_tls_curls_invoker.sh) to test CAPIF as invoker with TLS support. + +## cURL manual execution + +### Authentication +This version will use TLS communication, for that purpose we have 2 different scenarios, according to role: +* Invoker +* Provider + +#### Invoker +To authenticate an invoker user, we must perform next steps: +- Retrieve CA certificate from platform. [Retrieve and store CA certificate](#retrieve-and-store-ca-certificate) +- Register on the CAPIF with invoker role. [Register an entity](#register-an-entity) +- Get a Json Web Token (JWT) in order to request onboarding [Get access token for an existing entity](#get-access-token-for-an-existing-entity) +- Request onboarding adding public key to request. [Onboard an Invoker](#onboard-an-invoker) +- Store certificate signed by CAPIF platform to allow TLS onwards. + +**Flow:** + +![Flow](../images/flows/04%20-%20Invoker%20Register.png) +![Flow](../images/flows/05%20-%20Invoker%20Onboarding.png) + +#### Provider +To authenticate an provider user, we must perform next steps: +- Retrieve CA certificate from platform. [Retrieve and store CA certificate](#retrieve-and-store-ca-certificate) +- Register on the CAPIF with provider role. [Register an entity](#register-an-entity) +- Request sign the public key to CAPIF including beared with JWT. [Sign provider certificate](#sign-provider-certificate) +- Store certificate signed by CAPIF platform to allow TLS onwards. + +**Flow:** + +![Flow](../images/flows/01%20-%20Register%20del%20AEF.png) +![Flow](../images/flows/02%20-%20AEF%20API%20Provider%20registration.png) +![Flow](../images/flows/03%20-%20AEF%20Publish.png) + +### JWT Authentication APIs +These APIs are triggered by an entity (Invoker or Provider for release 1.0) to: +- register on the CAPIF Framework +- get a Json Web Token (JWT) in order to be authorized to call CAPIF APIs + +#### Register an entity +Request +```shell +curl --request POST 'http://:/register' --header 'Content-Type: application/json' --data '{ + "username":"...", + "password":"...", + "role":"...", + "description":"...", + "cn":"..." +}' +``` + +* Role: invoker or publisher +* cn: common name + +Response body +```json +{ + "id": "Entity ID", + "message": "Informative message" +} +``` + +#### Get access token for an existing entity +Request +```shell +curl --request POST 'http://:/gettoken' --header 'Content-Type: application/json' --data '{ + "username":"...", + "password":"...", + "role":"..." +}' +``` + +Response body +```json +{ + "access_token": "JSON Web Token for CAPIF APIs", + "message": "Informative message" +} +``` + +#### Retrieve and store CA certificate +```shell +curl --request GET 'http://:/ca-root' 2>/dev/null | jq -r '.certificate' -j > +``` + +#### Sign provider certificate +```shell +curl --request POST 'http:///sign-csr' --header 'Authorization: Bearer ' --header 'Content-Type: application/json' --data-raw '{ + "csr": "RAW PUBLIC KEY CREATED BY PUBLISHER", + "mode": "client", + "filename": provider +}' +``` +Response +``` json +{ + "certificate": "PUBLISHER CERTIFICATE" +} +``` +PUBLISHER CERTIFICATE value must be stored by Provider entity to next request to CAPIF (provider.crt for example) + +### Invoker Management APIs + +These APIs are triggered by a NetApp (i.e. Invoker) + +#### Onboard an Invoker + +```shell +curl --cacert --request POST 'https:///api-invoker-management/v1/onboardedInvokers' --header 'Authorization: Bearer ' --header 'Content-Type: application/json' --data-raw '{ + "notificationDestination" : "http://X:Y/netapp_callback", + "supportedFeatures" : "fffffff", + "apiInvokerInformation" : , + "websockNotifConfig" : { + "requestWebsocketUri" : true, + "websocketUri" : "websocketUri" + }, + "onboardingInformation" : { + "apiInvokerPublicKey" : + }, + "requestTestNotification" : true +}' +``` + +Response Body + +``` json +{ + "apiInvokerId": "7da0a8d4172d7d86c536c0fbc9c372", + "onboardingInformation": { + "apiInvokerPublicKey": "RAW PUBLIC KEY CREATED BY INVOKER", + "apiInvokerCertificate": "INVOKER CERTIFICATE", + "onboardingSecret": "onboardingSecret" + }, + "notificationDestination": "http://host.docker.internal:8086/netapp_callback", + "requestTestNotification": true, + ... +} +``` + +INVOKER CERTIFICATE value must be stored by Invoker entity to next request to CAPIF (invoker.crt for example) + +#### Update Invoker Details + +```shell +curl --location --request PUT 'https:///api-invoker-management/v1/onboardedInvokers/' --cert --key --cacert --header 'Content-Type: application/json' --data '{ + "notificationDestination" : "http://X:Y/netapp_callback2", + "supportedFeatures" : "fffffff", + "apiInvokerInformation" : , + "websockNotifConfig" : { + "requestWebsocketUri" : true, + "websocketUri" : "websocketUri2" + }, + "onboardingInformation" : { + "apiInvokerPublicKey" : + }, + "requestTestNotification" : true +}' +``` + +#### Offboard an Invoker + +```shell +curl --cert --key --cacert --request DELETE 'https:///api-invoker-management/v1/onboardedInvokers/' +``` + +### Publish APIs + +These APIs are triggered by the API Publishing Function (APF) of an Provider + +#### Publish a new API. +```shell +curl --cert --key --cacert --request POST 'https:///published-apis/v1//service-apis' --header 'Content-Type: application/json' --data '{ + "apiName": "3gpp-monitoring-event", + "aefProfiles": [ + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + } + ], + "description": "string", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" +}' +``` + +#### Update a published service API. +```shell +curl --cert --key --cacert --request PUT 'https:///published-apis/v1//service-apis/' --header 'Content-Type: application/json' --data '{ + "apiName": "3gpp-monitoring-event", + "aefProfiles": [ + { + "aefId": "string1", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + } + ], + "description": "string", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" +}' +``` + +#### Unpublish a published service API. +```shell +curl --cert --key --cacert --request DELETE 'https:///published-apis/v1//service-apis/' +``` + +#### Retrieve all published APIs +```shell +curl --cert --key --cacert --request GET 'https:///published-apis/v1//service-apis' +``` + +#### Retrieve a published service API. +```shell +curl --cert --key --cacert --request GET 'https:///published-apis/v1//service-apis/' +``` + +### Discover API + +This API is triggered by a NetApp (or Invoker) + +#### Discover published service APIs and retrieve a collection of APIs according to certain filter criteria. +```shell +curl --cert --key --cacert --request GET 'https:///service-apis/v1/allServiceAPIs?api-invoker-id=&api-name=&api-version=&aef-id=&api-cat=&supported-features=&api-supported-features=' +``` + + + +[Return To Main]: ../../README.md#using-curl \ No newline at end of file diff --git a/docs/testing_with_curl/capif_tls_curls_exposer.sh b/docs/testing_with_curl/capif_tls_curls_exposer.sh new file mode 100755 index 0000000..5b81712 --- /dev/null +++ b/docs/testing_with_curl/capif_tls_curls_exposer.sh @@ -0,0 +1,205 @@ +##### Execute Exposer curls locally + +##### Configure machine + +##### Add in /etc/hosts: 127.0.0.1 capifcore + + +##### Set environment variables +capifhost="capifcore" +capifhttpport="8080" + +exposerpk="-----BEGIN CERTIFICATE REQUEST-----\nMIIC0TCCAbkCAQAwgYsxEDAOBgNVBAMMB2V4cG9zZXIxFzAVBgNVBAoMDlRlbGVm\nb25pY2EgSStEMRMwEQYDVQQLDApJbm5vdmF0aW9uMQ8wDQYDVQQHDAZNYWRyaWQx\nDzANBgNVBAgMBk1hZHJpZDELMAkGA1UEBhMCRVMxGjAYBgkqhkiG9w0BCQEWC2lu\nbm9AdGlkLmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkpJ7FzAI\nkzFYxLKbW54lIsQBNIQz5zQIvRZDFcrO4QLR2jQUps9giBWEDih++47JiBJyM+z1\nWkEh7b+moZhQThj7L9PKgJHRhU1oeHpSE1x/r7479J5F+CFRqFo5v9dC+2zGfP4E\nsSrNfp3MK/KQHsHhMzSt881xAHs+p2/bcM+sd/BlXC4J6E1y6Hk3ogI7kq443fcY\noUHZx9ClUSboOvXa1ZSPVxdCV6xKRraUdAKfhMGn+pYtJDsNp8Gg/BN8NXmYUzl9\ntDhjeuIxr4N38LgW3gRHLNIa8acO9eBctWw9AD20JWzFAXvvmsboBPc2wsOVcsml\ncCbisMRKX4JyKQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAIxZ1Sec9ATbqjhi\nRz4rvhX8+myXhyfEw2MQ62jz5tpH4qIVZFtn+cZvU/ULySY10WHaBijGgx8fTaMh\nvjQbc+p3PXmgtnmt1QmoOGjDTFa6vghqpxPLSUjjCUe8yj5y24gkOImY6Cv5rzzQ\nlnTMkNvnGgpDgUeiqWcQNbwwge3zkzp9bVRgogTT+EDxiFnjTTF6iUG80sRtXMGr\nD6sygLsF2zijGGfWoKRo/7aZTQxuCiCixceVFXegMfr+eACkOjV25Kso7hYBoEdP\nkgUf5PNpl5uK3/rmPIrl/TeE0SnGGfCYP7QajE9ELRsBVmVDZJb7ZxUl1A4YydFY\ni0QOM3Y=\n-----END CERTIFICATE REQUEST-----\n" + + +##### Retrieve and store CA certificate + +curl --request GET "http://$capifhost:$capifhttpport/ca-root" 2>/dev/null | jq -r '.certificate' -j > ca.crt + + +##### Register an entity + +exposerid=$(curl --request POST "http://$capifhost:$capifhttpport/register" --header 'Content-Type: application/json' --data '{ + "username":"exposer", + "password":"exposer", + "role":"exposer", + "description":"Exposer", + "cn":"exposer" +}' 2>/dev/null | jq -r '.id' -j) + + +##### Get access token + +exposertoken=$(curl --request POST "http://$capifhost:$capifhttpport/gettoken" --header 'Content-Type: application/json' --data '{ + "username":"exposer", + "password":"exposer", + "role":"exposer" +}' 2>/dev/null | jq -r '.access_token' -j) + + +##### Sign exposer certificate + +curl --request POST "http://$capifhost:$capifhttpport/sign-csr" --header "Authorization: Bearer $exposertoken" --header 'Content-Type: application/json' --data-raw "{ + \"csr\": \"$exposerpk\", + \"mode\": \"client\", + \"filename\": \"exposer\" +}" 2>/dev/null | jq -r '.certificate' -j > exposer.crt + + +##### Publish service +curl --cert exposer.crt --key exposer.key --cacert ca.crt --request POST "https://$capifhost/published-apis/v1/$exposerid/service-apis" --header 'Content-Type: application/json' --data '{ + "apiName": "3gpp-monitoring-event", + "aefProfiles": [ + { + "aefId": "string", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + } + ], + "description": "string", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" +}' > response.json + +apiserviceid=$(cat response.json | jq -r '.apiId' -j) + + +##### Update a published service API +curl --cert exposer.crt --key exposer.key --cacert ca.crt --request PUT "https://$capifhost/published-apis/v1/$exposerid/service-apis/$apiserviceid" --header 'Content-Type: application/json' --data '{ + "apiName": "3gpp-monitoring-event", + "aefProfiles": [ + { + "aefId": "string1", + "versions": [ + { + "apiVersion": "v1", + "expiry": "2021-11-30T10:32:02.004Z", + "resources": [ + { + "resourceName": "string", + "commType": "REQUEST_RESPONSE", + "uri": "string", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ], + "custOperations": [ + { + "commType": "REQUEST_RESPONSE", + "custOpName": "string", + "operations": [ + "GET" + ], + "description": "string" + } + ] + } + ], + "protocol": "HTTP_1_1", + "dataFormat": "JSON", + "securityMethods": ["PSK"], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": ["PSK"] + } + ] + } + ], + "description": "string", + "supportedFeatures": "fffff", + "shareableInfo": { + "isShareable": true, + "capifProvDoms": [ + "string" + ] + }, + "serviceAPICategory": "string", + "apiSuppFeats": "fffff", + "pubApiPath": { + "ccfIds": [ + "string" + ] + }, + "ccfId": "string" +}' + + +##### Retrieve all published APIs + +curl --cert exposer.crt --key exposer.key --cacert ca.crt --request GET "https://$capifhost/published-apis/v1/$exposerid/service-apis" + + +##### Retrieve a published service API + +curl --cert exposer.crt --key exposer.key --cacert ca.crt --request GET "https://$capifhost/published-apis/v1/$exposerid/service-apis/$apiserviceid" + + +##### Unpublish a published service API + +curl --cert exposer.crt --key exposer.key --cacert ca.crt --request DELETE "https://$capifhost/published-apis/v1/$exposerid/service-apis/$apiserviceid" + + diff --git a/docs/testing_with_curl/capif_tls_curls_invoker.sh b/docs/testing_with_curl/capif_tls_curls_invoker.sh new file mode 100755 index 0000000..d6c287a --- /dev/null +++ b/docs/testing_with_curl/capif_tls_curls_invoker.sh @@ -0,0 +1,86 @@ +##### Execute Invoker curls locally + +##### Configure machine + +##### Add in /etc/hosts: 127.0.0.1 capifcore + + +##### Set environment variables + +capifhost="capifcore" +capifhttpport="8080" + +invokerpk="-----BEGIN CERTIFICATE REQUEST-----\nMIIC0TCCAbkCAQAwgYsxEDAOBgNVBAMMB2ludm9rZXIxFzAVBgNVBAoMDlRlbGVm\nb25pY2EgSStEMRMwEQYDVQQLDApJbm5vdmF0aW9uMQ8wDQYDVQQHDAZNYWRyaWQx\nDzANBgNVBAgMBk1hZHJpZDELMAkGA1UEBhMCRVMxGjAYBgkqhkiG9w0BCQEWC2lu\nbm9AdGlkLmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArfITEb3/\nJ5KDt7ia2WsQrd8iSrlH8kh6D9YNPEF+KaIGQ9w8QhmOW416uvIAASzOaCKMNqgb\nCI0NqsbVF9lfaiBgB71vcwX0yKatjACn3Nl3Lnubi+tH4Jb5zGQQXOuxpMHMmgyn\nNTsSc/MeMzX3iUWqLmmhnTC31Mu1ESUPTBa+CitQAj2wYMvBS970WICKrDlxWkR8\nZZBkRBZaxMfqY21VWmREtR+Kl6GCMBtUCUBH6uWjFiOpxYbCxdygxxrA4a3IzmiO\ntXOyLs7iuOP/CLSYfk71MHX2qKlpAyjdRK2W0w0GioV90Hk4uT/YUYy9zjWWN+mm\nrQ9GBy8iRZm7YwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAI0btA7KDMvkY4Ib\n0eMteeeT40bm11Yw8/6V48IaIPi9EpZMI+jWyCebw8PBFUs3l3ImWeO8Gma96gyf\np0WB/64MRkUSdOxUWOWGMPIMEF+BH3eiHthx+EbAETtJ0D4KzmH6raxl14qvwLS5\nwxtxPGxu/R5ue5RVJpAzzJ6OX36p05GYSzL+pTotVPpowSdoeNsV+xPgPA0diV8a\nB7Zn/ujwMpsh7IjQPKpOEkhQdxc478Si8dmRbzXkVar1Oa8/QSJ8ZAaFI4VGowjR\nmtxps7AvS5OG9iMPtFQHpqxHVO50CJU5cbsXsYdu9EipGhgIKJDKewBX7tCKk0Ot\nBLU03CY=\n-----END CERTIFICATE REQUEST-----\n" + + +##### Retrieve and store CA certificate + +curl --request GET "http://$capifhost:$capifhttpport/ca-root" 2>/dev/null | jq -r '.certificate' -j > ca.crt + + +##### Register an entity + +invokerid=$(curl --request POST "http://$capifhost:$capifhttpport/register" --header 'Content-Type: application/json' --data '{ + "username":"invoker", + "password":"invoker", + "role":"invoker", + "description":"Invoker", + "cn":"invoker" +}' 2>/dev/null | jq -r '.id' -j) + + +##### Get access token + +invokertoken=$(curl --request POST "http://$capifhost:$capifhttpport/gettoken" --header 'Content-Type: application/json' --data '{ + "username":"invoker", + "password":"invoker", + "role":"invoker" +}' 2>/dev/null | jq -r '.access_token' -j) + + +##### Onboard an Invoker + +curl --cacert ca.crt --request POST "https://$capifhost/api-invoker-management/v1/onboardedInvokers" --header "Authorization: Bearer $invokertoken" --header 'Content-Type: application/json' --data-raw "{ + \"notificationDestination\" : \"http://X:Y/netapp_callback\", + \"supportedFeatures\" : \"fffffff\", + \"apiInvokerInformation\" : \"invoker\", + \"websockNotifConfig\" : { + \"requestWebsocketUri\" : true, + \"websocketUri\" : \"websocketUri\" + }, + \"onboardingInformation\" : { + \"apiInvokerPublicKey\" : \"$invokerpk\" + }, + \"requestTestNotification\" : true +}" > response.json + +cat response.json | jq -r '.onboardingInformation.apiInvokerCertificate' -j > invoker.crt +apiinvokerid=$(cat response.json | jq -r '.apiInvokerId' -j) + + +##### Update Invoker Details + +curl --location --request PUT "https://$capifhost/api-invoker-management/v1/onboardedInvokers/$apiinvokerid" --cert invoker.crt --key invoker.key --cacert ca.crt --header 'Content-Type: application/json' --data "{ + \"notificationDestination\" : \"http://X:Y/netapp_callback2\", + \"supportedFeatures\" : \"fffffff\", + \"apiInvokerInformation\" : \"test\", + \"websockNotifConfig\" : { + \"requestWebsocketUri\" : true, + \"websocketUri\" : \"websocketUri2\" + }, + \"onboardingInformation\" : { + \"apiInvokerPublicKey\" : \"$invokerpk\" + }, + \"requestTestNotification\" : true +}" + + +##### Discover API + +curl --cert invoker.crt --key invoker.key --cacert ca.crt --request GET "https://$capifhost/service-apis/v1/allServiceAPIs?api-invoker-id=$apiinvokerid" + + +##### Offboard an Invoker + +curl --cert invoker.crt --key invoker.key --cacert ca.crt --request DELETE "https://$capifhost/api-invoker-management/v1/onboardedInvokers/$apiinvokerid" + diff --git a/docs/testing_with_curl/exposer.key b/docs/testing_with_curl/exposer.key new file mode 100644 index 0000000..e84c8c4 --- /dev/null +++ b/docs/testing_with_curl/exposer.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCSknsXMAiTMVjE +sptbniUixAE0hDPnNAi9FkMVys7hAtHaNBSmz2CIFYQOKH77jsmIEnIz7PVaQSHt +v6ahmFBOGPsv08qAkdGFTWh4elITXH+vvjv0nkX4IVGoWjm/10L7bMZ8/gSxKs1+ +ncwr8pAeweEzNK3zzXEAez6nb9twz6x38GVcLgnoTXLoeTeiAjuSrjjd9xihQdnH +0KVRJug69drVlI9XF0JXrEpGtpR0Ap+Ewaf6li0kOw2nwaD8E3w1eZhTOX20OGN6 +4jGvg3fwuBbeBEcs0hrxpw714Fy1bD0APbQlbMUBe++axugE9zbCw5VyyaVwJuKw +xEpfgnIpAgMBAAECggEACs11TqlcIG5qd/N1Ts8ni9noACpe4ZiXV578lRkW8++E +xEZtX+P4iIm+wK+3DYGhvyp430naGsD30rF62FMaVr8xmCijC/nIoutTGqS38t8G +Ns+C/2Lrjj+fvemJyGasSaKOjdIc9L/OWG7MiE/+05LU2bTKvfrIwXvT4NGg2ei1 +NDO8vS5fRHYZ1LyCyrCDetP2aYrTlPao20hmU4IDyh4N17wLuPgijC+AuqR2Xic0 +Mk4ofZ/6Y3oN0rrov2yG7IXjMJQI469IQ6TJLlyFc8tQIF5Y3CMMCMuVMq5m33bq +/6bow4/VYFG8mPzy7lQLQ8YeEPsgDKL0pB4zqDr7ZwKBgQDJRJoG2PSaEOt6DIKV +84to73oD9x9lOSrmaH2/NzL3mwLXP2Is4nmLzEDQvA0UhTZe9c0n6OoE3uRZ1gAu +JIe3zXTJSK4/ysmePUZL1js5bKtuHBrcSCOupWRuJXbaXK5uqISDHUgHiRw3bq8y +g8SZY/JOBPyJhVlKhmhNCYMi9wKBgQC6bjJ//tLpH6EG4ux0O2StzUoHrvV2cyUj +RRxGvAt92sdsZaVKmIW/SlLy8tv5HJqblfn6m7aY/vUYbN3AfMJ4teLZz5Y//CH3 +jPchHyk/uhh7gxufiD65i5bfVyRt54tDbyVDc2/1prUyD5W4q4UNOmvhXym5saIc +U5WNCnSr3wKBgQCs8MaM5bVgAPPlfoRixs9ejo/AgoK2nqWvL9AFEzA3NDn/rJX2 +TW/1YL+83Ck9Ha33cKwlA+y53LBIRSsIexknJWKZZltbsysFTk9t8JoZILg5N+sY +puAKPFGMl6KFxSeZLDIY23s+BmF5fCEMfc7botbclUpN/IgaEl3i/C5zRwKBgHsx +lKdmEaNBZlwxmgTYtpfvH2tiXwwN3M2ovp2zZ3icGMn1hTt8/GzCxXuLpnbAQx5r +BcxoF0qUuAuS7RpklvHDZ4t9FJFloGCAQ1Ic0FovNDxyD8/k7WYY6vLdF9KUfj9q +c9pVrvdKWVQiXlKw7PQn1eAQzXbK/g/v39Raw2xLAoGBAILTLY3sGBNkFCVhJlyZ +DaIwkbtnpCBT2T7DUupw51aLhh4rnuJ5wA3uGdRqoKVYSc9DuOwB/yNFGuQDElxQ +jfKlX0X5xItaxZ5FR4EvGCnqBJl6JM3QekzhXtq5VdY5zIf/HHqFYebcMFrkEicZ +uuAZd4wa+jn9SR9mUYtS+Lq+ +-----END PRIVATE KEY----- diff --git a/docs/testing_with_curl/invoker.key b/docs/testing_with_curl/invoker.key new file mode 100644 index 0000000..15b96bb --- /dev/null +++ b/docs/testing_with_curl/invoker.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCt8hMRvf8nkoO3 +uJrZaxCt3yJKuUfySHoP1g08QX4pogZD3DxCGY5bjXq68gABLM5oIow2qBsIjQ2q +xtUX2V9qIGAHvW9zBfTIpq2MAKfc2Xcue5uL60fglvnMZBBc67GkwcyaDKc1OxJz +8x4zNfeJRaouaaGdMLfUy7URJQ9MFr4KK1ACPbBgy8FL3vRYgIqsOXFaRHxlkGRE +FlrEx+pjbVVaZES1H4qXoYIwG1QJQEfq5aMWI6nFhsLF3KDHGsDhrcjOaI61c7Iu +zuK44/8ItJh+TvUwdfaoqWkDKN1ErZbTDQaKhX3QeTi5P9hRjL3ONZY36aatD0YH +LyJFmbtjAgMBAAECggEAAyR5OxdJ1W5jnSD9kBCvO6jDMIUuIcU+SAZUfGaxYybn +EeNCtBiPGV8tWWLHJJ0bL6iKpAv+gOKeSpKOmwU7XkHZEWVlRAfpiNfen2bcTCiw +fg3D4bgRMmDwwyMH368QFlJ56UFMCuqb0x+oCeMRIdNjwfbcPVCpZDYNGwTDBzoy +72Aj5TssEu+Ft5VVGwhsvq0v6bd6OWmW34PI9SHzXzRlRw4b4ZtZekW8o/QpO1gO +F+ARbCGE2qjqHWRU/vzINMmAucqhDM6/f7Un5XXr+Zm+8u4PGa5eLWkebJHhfwKX +Ag0WToD/FmDPRqlnjZdzraJlhuXLGdhRAlzdnIQNRQKBgQDvhiVewu7CTzgB66dA +cdrJkXVJPZUGvUYmXkwPaSju7hjDc87pNz+szH2QP+Qm+pD1mV9OswIim4Oi7C1l +lEe423QGjtsn5txzcRk+ZzyX/Z2ltcnXi8N/MNeOZ2qFAgP/IIOTcgowKftuUT6w +2A1DQFj6xxu6vrzxOqIL6tXy7wKBgQC56SM80udTqyb9+wk/KuDSgym3bSaZ8i5q +dNVV5wOxCotLGG9Any61TVOIP/SUjar4f4+FznLZjJYXIZvpbS32PUOtlnKtOmp6 +OBKIpEXq2zq0u/o/i8EyOb6laNqehfffRYqqYU9mJXVjiTUNcOVqfLljeeui1r1P +txSRBlTuzQKBgQDUgB/hbXHjw+J9mbM9soUXtUvn2ZHAc+Wrnpc+SN6+80/W/4R/ +VbvRM27mrjhc+InoytRKfvgS+gOUZJJ1/1KOR2wtcUovoVrNtHZf7blNYv0dCiXz +bBTaX9uthER1km83RoJVKqStTGG74qqKvHMvygPnIQSR7iy0m38usX500wKBgGeM +koLzWcOBhhNa+tiDMnwucFLpaeG/QdkrwBO7u5OlstYeAwF0aFi1fDxcmwcPLVaB +/lfiGJhRtNunbacDl+EaWJLcRH12Fw6CItiW3xakCzvVo9o3JmGqRiTtlS9MoTZs +DoM99jKH1K2fI7yb0DySwdPFedjWUNWQvNTWOQJVAoGAYr9Kuo7s83Qe9CaHQW/Y +PPL0dYBA63guuw2mNQjBL5LuqMZPz6vVB0hIVlYb5Xgw48OWUThHksJ0qltJK7kR +OPRyOxiWpJVo5rZPVzS0Ofbmau9z1VYr358RqR2N2EqG5KDr5QZT9nQq7k8EJvrF +NM/zMhxmgtNYez417Q/3U+M= +-----END PRIVATE KEY----- diff --git a/docs/testing_with_postman/CAPIF.postman_collection.json b/docs/testing_with_postman/CAPIF.postman_collection.json new file mode 100644 index 0000000..e65c826 --- /dev/null +++ b/docs/testing_with_postman/CAPIF.postman_collection.json @@ -0,0 +1,982 @@ +{ + "info": { + "_postman_id": "5cfdf0d7-3b3c-4961-9cb9-84c2bf85056c", + "name": "CAPIF", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "31608242", + "_collection_link": "https://red-comet-993867.postman.co/workspace/Team-Workspace~bfc7c442-a60c-4bb1-8730-fdabc2df89b9/collection/31608242-5cfdf0d7-3b3c-4961-9cb9-84c2bf85056c?action=share&source=collection_link&creator=31608242" + }, + "item": [ + { + "name": "01-register_user_provider", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "pm.environment.set('ONBOARDING_URL', res.ccf_api_onboarding_url);", + "pm.environment.set('PUBLISH_URL', res.ccf_publish_url);", + "pm.environment.set('USER_ID', res.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME}}\",\n\"description\": \"provider\",\n\"role\": \"provider\",\n\"cn\": \"provider\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/register", + "protocol": "https", + "host": [ + "{{REGISTER_HOSTNAME}}" + ], + "port": "{{REGISTER_PORT}}", + "path": [ + "register" + ] + } + }, + "response": [] + }, + { + "name": "02-getauth_provider", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "", + "pm.environment.set('CA_ROOT', res.ca_root);", + "pm.environment.set('ACCESS_TOKEN', res.access_token);", + "", + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_ca',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: res", + " }", + " }, function (err, res) {", + " console.log(res);", + " });", + " }, 5000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/getauth", + "protocol": "https", + "host": [ + "{{REGISTER_HOSTNAME}}" + ], + "port": "{{REGISTER_PORT}}", + "path": [ + "getauth" + ] + } + }, + "response": [] + }, + { + "name": "03-onboard_provider", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "if (pm.response.code == 201){", + " ", + " pm.environment.set('PROVIDER_ID', res.apiProvDomId);", + "", + " const roleVariableMapping = {", + " \"AEF\": { id: 'AEF_ID', cert: 'AEF_CERT' },", + " \"APF\": { id: 'APF_ID', cert: 'APF_CERT' },", + " \"AMF\": { id: 'AMF_ID', cert: 'AMF_CERT' }", + " };", + "", + " res.apiProvFuncs.forEach(function(elemento) {", + " const role = elemento.apiProvFuncRole;", + " if (roleVariableMapping.hasOwnProperty(role)) {", + " const variables = roleVariableMapping[role];", + " pm.environment.set(variables.id, elemento.apiProvFuncId);", + " pm.environment.set(variables.cert, elemento.regInfo.apiProvCert);", + "", + " }", + " });", + "", + "}", + "", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "", + "var res = JSON.parse(pm.request.body.raw);", + "", + "res.apiProvFuncs.forEach(function(elemento) {", + "", + " setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/generate_csr',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: elemento", + " }", + " }, function (err, response) {", + " j_file = JSON.parse(response.text());", + " elemento.regInfo.apiProvPubKey = j_file.csr;", + " pm.environment.set(elemento.apiProvFuncRole+'_KEY', j_file.key);", + " });", + " }, 5000);", + "", + "});", + "", + "pm.request.body.raw = res;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{ACCESS_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\n\"apiProvFuncs\": [\n {\n \"regInfo\": {\n \"apiProvPubKey\": \"\"\n },\n \"apiProvFuncRole\": \"AEF\",\n \"apiProvFuncInfo\": \"dummy_aef\"\n },\n {\n \"regInfo\": {\n \"apiProvPubKey\": \"\"\n },\n \"apiProvFuncRole\": \"APF\",\n \"apiProvFuncInfo\": \"dummy_apf\"\n },\n {\n \"regInfo\": {\n \"apiProvPubKey\": \"\"\n },\n \"apiProvFuncRole\": \"AMF\",\n \"apiProvFuncInfo\": \"dummy_amf\"\n }\n],\n\"apiProvDomInfo\": \"This is provider\",\n\"suppFeat\": \"fff\",\n\"failReason\": \"string\",\n\"regSec\": \"{{ACCESS_TOKEN}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL}}", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "{{ONBOARDING_URL}}" + ] + } + }, + "response": [] + }, + { + "name": "04-publish_api", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_cert',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: {cert: pm.environment.get('APF_CERT'), key:pm.environment.get('APF_KEY')}", + " }", + " }, function (err, response) {", + " console.log(response)", + " });", + " }, 5000);", + "", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "strictSSL": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "\n{\n \"apiName\": \"hello_api_demo_v2\",\n \"aefProfiles\": [\n {\n \"aefId\": \"{{AEF_ID}}\",\n \"versions\": [\n {\n \"apiVersion\": \"v1\",\n \"expiry\": \"2021-11-30T10:32:02.004Z\",\n \"resources\": [\n {\n \"resourceName\": \"hello-endpoint\",\n \"commType\": \"REQUEST_RESPONSE\",\n \"uri\": \"/hello\",\n \"custOpName\": \"string\",\n \"operations\": [\n \"POST\"\n ],\n \"description\": \"Endpoint to receive a welcome message\"\n }\n ],\n \"custOperations\": [\n {\n \"commType\": \"REQUEST_RESPONSE\",\n \"custOpName\": \"string\",\n \"operations\": [\n \"POST\"\n ],\n \"description\": \"string\"\n }\n ]\n }\n ],\n \"protocol\": \"HTTP_1_1\",\n \"dataFormat\": \"JSON\",\n \"securityMethods\": [\"Oauth\"],\n \"interfaceDescriptions\": [\n {\n \"ipv4Addr\": \"localhost\",\n \"port\": 8088,\n \"securityMethods\": [\"Oauth\"]\n }\n ]\n }\n ],\n \"description\": \"Hello api services\",\n \"supportedFeatures\": \"fffff\",\n \"shareableInfo\": {\n \"isShareable\": true,\n \"capifProvDoms\": [\n \"string\"\n ]\n },\n \"serviceAPICategory\": \"string\",\n \"apiSuppFeats\": \"fffff\",\n \"pubApiPath\": {\n \"ccfIds\": [\n \"string\"\n ]\n },\n \"ccfId\": \"string\"\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/published-apis/v1/{{APF_ID}}/service-apis", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "published-apis", + "v1", + "{{APF_ID}}", + "service-apis" + ] + } + }, + "response": [] + }, + { + "name": "05-register_user_invoker", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "pm.environment.set('ONBOARDING_URL_INVOKER', res.ccf_onboarding_url);", + "pm.environment.set('DISCOVER_URL', res.ccf_discover_url);", + "pm.environment.set('USER_INVOKER_ID', res.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME_INVOKER}}\",\n\"description\": \"invoker\",\n\"role\": \"invoker\",\n\"cn\": \"invoker\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/register", + "protocol": "https", + "host": [ + "{{REGISTER_HOSTNAME}}" + ], + "port": "{{REGISTER_PORT}}", + "path": [ + "register" + ] + } + }, + "response": [] + }, + { + "name": "06-getauth_invoker", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "", + "pm.environment.set('CA_ROOT', res.ca_root);", + "pm.environment.set('ACCESS_TOKEN_INVOKER', res.access_token);", + "", + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_ca',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: res", + " }", + " }, function (err, res) {", + " console.log(res);", + " });", + " }, 5000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME_INVOKER}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/getauth", + "protocol": "https", + "host": [ + "{{REGISTER_HOSTNAME}}" + ], + "port": "{{REGISTER_PORT}}", + "path": [ + "getauth" + ] + } + }, + "response": [] + }, + { + "name": "07-onboard_invoker", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "if (pm.response.code == 201){", + " ", + " pm.environment.set('INVOKER_ID', res.apiInvokerId);", + " pm.environment.set('INVOKER_CERT', res.onboardingInformation.apiInvokerCertificate);", + "}", + "", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "", + "var res = JSON.parse(pm.request.body.raw);", + "", + "", + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/generate_csr_invoker',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: {}", + " }", + " }, function (err, response) {", + " j_file = JSON.parse(response.text());", + " res.onboardingInformation.apiInvokerPublicKey = j_file.csr;", + " pm.environment.set('INVOKER_KEY', j_file.key);", + " });", + " }, 5000);", + "", + "", + "pm.request.body.raw = res;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{ACCESS_TOKEN_INVOKER}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"notificationDestination\" : \"http://host.docker.internal:8086/netapp_callback\",\n \"supportedFeatures\" : \"fffffff\",\n \"apiInvokerInformation\" : \"dummy\",\n \"websockNotifConfig\" : {\n \"requestWebsocketUri\" : true,\n \"websocketUri\" : \"websocketUri\"\n },\n \"onboardingInformation\" : {\n \"apiInvokerPublicKey\" : \"\"\n },\n \"requestTestNotification\" : true\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL_INVOKER}}", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "{{ONBOARDING_URL_INVOKER}}" + ] + } + }, + "response": [] + }, + { + "name": "08-discover", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_cert',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", + " }", + " }, function (err, response) {", + " console.log(response)", + " });", + " }, 5000);", + "", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "if (pm.response.code == 200){", + "", + " res.serviceAPIDescriptions.forEach(function(api) {", + " pm.environment.set('API_SERVICE_ID', api.apiId);", + " pm.environment.set('API_NAME', api.apiName);", + " pm.environment.set('API_AEF_ID', api.aefProfiles[0].aefId);", + " pm.environment.set('IPV4ADDR', api.aefProfiles[0].interfaceDescriptions[0].ipv4Addr);", + " pm.environment.set('PORT', api.aefProfiles[0].interfaceDescriptions[0].port);", + " pm.environment.set('URI', api.aefProfiles[0].versions[0].resources[0].uri);", + " });", + "}" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true, + "strictSSL": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/{{DISCOVER_URL}}{{INVOKER_ID}}", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "{{DISCOVER_URL}}{{INVOKER_ID}}" + ] + } + }, + "response": [] + }, + { + "name": "09-security_context", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_cert',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", + " }", + " }, function (err, response) {", + " console.log(response)", + " });", + " }, 5000);", + "", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "strictSSL": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "PUT", + "header": [ + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"securityInfo\": [\n {\n \"prefSecurityMethods\": [\n \"Oauth\"\n ],\n \"authenticationInfo\": \"string\",\n \"authorizationInfo\": \"string\",\n \"aefId\": \"{{API_AEF_ID}}\",\n \"apiId\": \"{{API_SERVICE_ID}}\"\n }\n ],\n \"notificationDestination\": \"https://mynotificationdest.com\",\n \"requestTestNotification\": true,\n \"websockNotifConfig\": {\n \"websocketUri\": \"string\",\n \"requestWebsocketUri\": true\n },\n \"supportedFeatures\": \"fff\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/capif-security/v1/trustedInvokers/{{INVOKER_ID}}", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "capif-security", + "v1", + "trustedInvokers", + "{{INVOKER_ID}}" + ] + } + }, + "response": [] + }, + { + "name": "10-get_token", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_cert',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", + " }", + " }, function (err, response) {", + " console.log(response)", + " });", + " }, 5000);", + "", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "var res = JSON.parse(responseBody);", + "if (pm.response.code == 200){", + " pm.environment.set('NETAPP_SERVICE_TOKEN', res.access_token);", + "}" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "strictSSL": true, + "disabledSystemHeaders": {} + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "client_id", + "value": "{{INVOKER_ID}}", + "type": "text" + }, + { + "key": "grant_type", + "value": "client_credentials", + "type": "text" + }, + { + "key": "client_secret", + "value": "string", + "type": "text" + }, + { + "key": "scope", + "value": "3gpp#{{API_AEF_ID}}:{{API_NAME}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/capif-security/v1/securities/{{INVOKER_ID}}/token", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "capif-security", + "v1", + "securities", + "{{INVOKER_ID}}", + "token" + ] + } + }, + "response": [] + }, + { + "name": "11-call_service", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "strictSSL": false + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{NETAPP_SERVICE_TOKEN}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\n\"name\": {{USERNAME_INVOKER}}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://{{IPV4ADDR}}:{{PORT}}{{URI}}", + "protocol": "http", + "host": [ + "{{IPV4ADDR}}" + ], + "port": "{{PORT}}{{URI}}" + } + }, + "response": [] + }, + { + "name": "offboard_provider", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_cert',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: {cert: pm.environment.get('AMF_CERT'), key:pm.environment.get('AMF_KEY')}", + " }", + " }, function (err, response) {", + " console.log(response)", + " });", + " }, 5000);" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "strictSSL": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL}}/{{PROVIDER_ID}}", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "{{ONBOARDING_URL}}", + "{{PROVIDER_ID}}" + ] + } + }, + "response": [] + }, + { + "name": "offboard_invoker", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(() => {", + " pm.sendRequest({", + " url: 'http://localhost:3000/write_cert',", + " method: 'POST',", + " header: 'Content-Type:application/json',", + " encoding: 'binary',", + " body: {", + " mode: 'raw',", + " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", + " }", + " }, function (err, response) {", + " console.log(response)", + " });", + " }, 5000);" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "strictSSL": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL_INVOKER}}/{{INVOKER_ID}}", + "protocol": "https", + "host": [ + "{{CAPIF_HOSTNAME}}" + ], + "path": [ + "{{ONBOARDING_URL_INVOKER}}", + "{{INVOKER_ID}}" + ] + } + }, + "response": [] + }, + { + "name": "remove_user_invoker", + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME_INVOKER}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/remove", + "protocol": "https", + "host": [ + "{{REGISTER_HOSTNAME}}" + ], + "port": "{{REGISTER_PORT}}", + "path": [ + "remove" + ] + } + }, + "response": [] + }, + { + "name": "remove_user_provider", + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/remove", + "protocol": "https", + "host": [ + "{{REGISTER_HOSTNAME}}" + ], + "port": "{{REGISTER_PORT}}", + "path": [ + "remove" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/docs/testing_with_postman/CAPIF.postman_environment.json b/docs/testing_with_postman/CAPIF.postman_environment.json new file mode 100644 index 0000000..ab3839e --- /dev/null +++ b/docs/testing_with_postman/CAPIF.postman_environment.json @@ -0,0 +1,237 @@ +{ + "id": "f2daf431-63c4-4275-8755-4cc5de2e566d", + "name": "CAPIF", + "values": [ + { + "key": "CAPIF_HOSTNAME", + "value": "capifcore", + "type": "default", + "enabled": true + }, + { + "key": "CAPIF_PORT", + "value": "8080", + "type": "default", + "enabled": true + }, + { + "key": "REGISTER_HOSTNAME", + "value": "localhost", + "type": "default", + "enabled": true + }, + { + "key": "REGISTER_PORT", + "value": "8084", + "type": "default", + "enabled": true + }, + { + "key": "USERNAME", + "value": "ProviderONE", + "type": "default", + "enabled": true + }, + { + "key": "PASSWORD", + "value": "pass", + "type": "default", + "enabled": true + }, + { + "key": "CALLBACK_IP", + "value": "host.docker.internal", + "type": "default", + "enabled": true + }, + { + "key": "CALLBACK_PORT", + "value": "8087", + "type": "default", + "enabled": true + }, + { + "key": "ONBOARDING_URL", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "PUBLISH_URL", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "USER_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "CA_ROOT", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "ACCESS_TOKEN", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "APF_KEY", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "AMF_KEY", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "AEF_KEY", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "PROVIDER_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "AEF_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "AEF_CERT", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "APF_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "APF_CERT", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "AMF_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "AMF_CERT", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "ONBOARDING_URL_INVOKER", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "DISCOVER_URL", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "USER_INVOKER_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "ACCESS_TOKEN_INVOKER", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "INVOKER_KEY", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "INVOKER_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "INVOKER_CERT", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "API_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "API_NAME", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "IPV4ADDR", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "PORT", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "URI", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "API_SERVICE_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "API_AEF_ID", + "value": "", + "type": "any", + "enabled": true + }, + { + "key": "NETAPP_SERVICE_TOKEN", + "value": "", + "type": "any", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2023-12-20T10:47:32.128Z", + "_postman_exported_using": "Postman/10.21.4" +} \ No newline at end of file diff --git a/docs/testing_with_postman/README.md b/docs/testing_with_postman/README.md new file mode 100644 index 0000000..6d36b32 --- /dev/null +++ b/docs/testing_with_postman/README.md @@ -0,0 +1,108 @@ +[**[Return To Main]**] + +# CAPIF in Postman +In this section we can use Postman to publish an API as a provider and use it as an invoker. + +## Requisites + +- We will need to have Node.js installed since we will use a small script to create the CSRs of the certificates. +- An instance of CAPIF (If it is not local, certain variables would have to be modified both in the Node.js script and in the Postman environment variables). + +## First steps + +1. Install the Node dependencies to run the script with: + +``` +npm i +``` + +2. Run the script.js with the following command: + +``` +node script.js +``` + +3. Import Postman collection and environment variables (CAPIF.postman_collection.json and CAPIF.postman_environment.json) + +## Not Local CAPIF + +If the CAPIF is not local, the host and port of both the CAPIF and the register would have to be specified in the variables, and the CAPIF_HOSTNAME in the script, necessary to obtain the server certificate. + +**Enviroments in Postman** +``` +CAPIF_HOSTNAME capifcore +CAPIF_PORT 8080 +REGISTER_HOSTNAME register +REGISTER_PORT 8084 +``` + +**Const in script.js** +``` +CAPIF_HOSTNAME capifcore +``` + +## CAPIF Flow +Once the first steps have been taken, we can now use Postman requests. These requests are numbered in the order that must be followed to obtain everything necessary from CAPIF. + +### Publication of an API + +- **01-register_user_provider** +- **02-getauth_provider** +- **03-onboard_provider** + +At this point we move on to using certificate authentication in CAPIF. In Postman it is necessary to add the certificates manually and using more than one certificate for the same host as we do in CAPIF complicates things. For this reason, we use the script to overwrite a certificate and a key when it is necessary to have a specific one. + +To configure go to **settings** in Postman and open the **certificates** section. + +- Here, activate the **CA certificates** option and add the **ca_cert.pem** file found in the **Responses** folder. +- Adds a client certificate specifying the CAPIF host being used and the files **client_cert.crt** and **client_key.key** in the **Responses** folder. + + +Once this is done, the node script will be in charge of changing the certificate that is necessary in each request. + +- **04-publish_api** + +Once the api is published, we can start it. In this case we have a test one created in python that can be executed with the following command: + +``` +python3 hello_api.py +``` + +The API publication interface is set to localhost with port 8088, so the service must be set up locally. If you wanted to build it on another site, you would have to change the interface description in the body of publish_api. + +With this the provider part would be finished. + +### Calling the API + +- **05-register_user_invoker** +- **06-getauth_invoker** +- **07-onboard_invoker** + +At this point we move on to using certificate authentication in CAPIF. **If you did not configure the provider's certificates, you would have to do it now**. + +- **08-discover** +- **09-security_context** +- **10-get_token** +- **11-call_service** + +With this, we would have made the API call and finished the flow. + +### Other requests + +Other requests that we have added are the following: + +- **offboard_provider** Performs offboarding of the provider, thereby eliminating the published APIs. +- **offboard_invoker** Offboards the invoker, also eliminating access to the APIs of that invoker. +- **remove_user_invoker** Delete the user created for the invoker. +- **remove_user_provider** Delete the user created for the provider. + +## Notes + +- This process is designed to teach how requests are made in Postman and the flow that should be followed to publish and use an API. +- It is possible that if external CAPIFs are used (Public CAPIF) the test data may already be used or the API already registered. +- It is necessary to have the Node service running to make the certificate change for the requests, otherwise it will not work. +- We are working on adding more requests to the Postman collection. +- This collection is a testing guide and is recommended for testing purposes only. + +[Return To Main]: ../../README.md#using-postman + diff --git a/docs/testing_with_postman/hello_api.py b/docs/testing_with_postman/hello_api.py new file mode 100644 index 0000000..0b2a359 --- /dev/null +++ b/docs/testing_with_postman/hello_api.py @@ -0,0 +1,38 @@ +from flask import Flask, jsonify, request +from flask_jwt_extended import jwt_required, JWTManager, get_jwt_identity, get_jwt +import ssl +from werkzeug import serving +import socket, ssl +import OpenSSL +from OpenSSL import crypto +import jwt +import pyone + +app = Flask(__name__) + +jwt_flask = JWTManager(app) + + +with open("Responses/cert_server.pem", "rb") as cert_file: + cert= cert_file.read() + +crtObj = crypto.load_certificate(crypto.FILETYPE_PEM, cert) +pubKeyObject = crtObj.get_pubkey() +pubKeyString = crypto.dump_publickey(crypto.FILETYPE_PEM,pubKeyObject) + +app.config['JWT_ALGORITHM'] = 'RS256' +app.config['JWT_PUBLIC_KEY'] = pubKeyString + + +@app.route("/hello", methods=["POST"]) +@jwt_required() +def hello(): + + request_data = request.get_json() + + user_name = request_data['name'] + + return jsonify(f"Hello: {user_name}, welcome to CAPIF.") + +if __name__ == '__main__': + serving.run_simple("0.0.0.0", 8088, app) diff --git a/docs/testing_with_postman/package.json b/docs/testing_with_postman/package.json new file mode 100644 index 0000000..6d612a7 --- /dev/null +++ b/docs/testing_with_postman/package.json @@ -0,0 +1,16 @@ +{ + "name": "node-server", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "body-parser": "^1.18.3", + "express": "^4.16.3", + "shelljs": "^0.8.2" + } + } \ No newline at end of file diff --git a/docs/testing_with_postman/script.js b/docs/testing_with_postman/script.js new file mode 100644 index 0000000..980f81f --- /dev/null +++ b/docs/testing_with_postman/script.js @@ -0,0 +1,199 @@ +// Change this variable if another host is used for CAPIF +const CAPIF_HOSTNAME = 'capifcore'; + +const express = require('express'), + app = express(), + fs = require('fs'), + shell = require('shelljs'), + + + folderPath = './Responses/', + bodyParser = require('body-parser'), + path = require('path'); + +const { exec } = require('child_process'); + +// Create the folder path in case it doesn't exist +shell.mkdir('-p', folderPath); + + // Change the limits according to your response size +app.use(bodyParser.json({limit: '50mb', extended: true})); +app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); +var opensslCommand = '' + +if (CAPIF_HOSTNAME.includes(':')){ + opensslCommand = `openssl s_client -connect ${CAPIF_HOSTNAME} | openssl x509 -text > ./Responses/cert_server.pem`; +} +else{ + opensslCommand = `openssl s_client -connect ${CAPIF_HOSTNAME}:443 | openssl x509 -text > ./Responses/cert_server.pem`; +} + +exec(opensslCommand, (error, stdout, stderr) => { + if (error) { + console.error(`Error generating CSR: ${stderr}`); + } +}); + +fs.writeFileSync('./Responses/client_cert.crt', ''); +fs.writeFileSync('./Responses/client_key.key', ''); + +app.get('/', (req, res) => res.send('Hello, I write data to file. Send them requests!')); + +app.post('/generate_csr', (req, res) => { + + console.log(req.body); + const csrFilePath = 'Responses/'+req.body.apiProvFuncRole+'_csr.pem'; + const privateKeyFilePath = 'Responses/'+req.body.apiProvFuncRole+'_key.key'; + + const subjectInfo = { + country: 'ES', + state: 'Madrid', + locality: 'Madrid', + organization: 'Telefonica I+D', + organizationalUnit: 'IT Department', + emailAddress: 'admin@example.com', + }; + + const opensslCommand = `openssl req -newkey rsa:2048 -nodes -keyout ${privateKeyFilePath} -out ${csrFilePath} -subj "/C=${subjectInfo.country}/ST=${subjectInfo.state}/L=${subjectInfo.locality}/O=${subjectInfo.organization}/OU=${subjectInfo.organizationalUnit}/emailAddress=${subjectInfo.emailAddress}"`; + + exec(opensslCommand, (error, stdout, stderr) => { + if (error) { + console.error(`Error generating CSR: ${stderr}`); + } else { + console.log('CSR generated successfully:'); + fs.readFile(csrFilePath, 'utf8', (readError, csrContent) => { + if (readError) { + console.error(`Error reading CSR: ${readError}`); + res.status(500).send('Error reading CSR'); + } else { + console.log('CSR read successfully:'); + // Send the CSR content in the response + fs.readFile(privateKeyFilePath, 'utf8', (readError, keyContent) => { + if (readError) { + console.error(`Error reading KEY: ${readError}`); + res.status(500).send('Error reading KEY'); + } else { + console.log('KEY read successfully:'); + // Send the CSR content in the response + fs.unlink(csrFilePath, (err) => { + if (err) { + console.error(`Error deleting file: ${err.message}`); + } + }); + fs.unlink(privateKeyFilePath, (err) => { + if (err) { + console.error(`Error deleting file: ${err.message}`); + } + }); + res.send({csr: csrContent, key: keyContent}); + } + }); + } + }); + } + }); +}); + +app.post('/generate_csr_invoker', (req, res) => { + + console.log(req.body); + const csrFilePath = 'Responses/invoker_csr.pem'; + const privateKeyFilePath = 'Responses/invoker_key.key'; + + const subjectInfo = { + country: 'ES', + state: 'Madrid', + locality: 'Madrid', + organization: 'Telefonica I+D', + organizationalUnit: 'IT Department', + emailAddress: 'admin@example.com', + }; + + const opensslCommand = `openssl req -newkey rsa:2048 -nodes -keyout ${privateKeyFilePath} -out ${csrFilePath} -subj "/C=${subjectInfo.country}/ST=${subjectInfo.state}/L=${subjectInfo.locality}/O=${subjectInfo.organization}/OU=${subjectInfo.organizationalUnit}/emailAddress=${subjectInfo.emailAddress}"`; + + exec(opensslCommand, (error, stdout, stderr) => { + if (error) { + console.error(`Error generating CSR: ${stderr}`); + } else { + console.log('CSR generated successfully:'); + fs.readFile(csrFilePath, 'utf8', (readError, csrContent) => { + if (readError) { + console.error(`Error reading CSR: ${readError}`); + res.status(500).send('Error reading CSR'); + } else { + console.log('CSR read successfuly:'); + // Send the CSR content in the response + fs.readFile(privateKeyFilePath, 'utf8', (readError, keyContent) => { + if (readError) { + console.error(`Error reading KEY: ${readError}`); + res.status(500).send('Error reading KEY'); + } else { + console.log('KEY read successfully:'); + // Send the CSR content in the response + fs.unlink(csrFilePath, (err) => { + if (err) { + console.error(`Error deleting file: ${err.message}`); + } + }); + fs.unlink(privateKeyFilePath, (err) => { + if (err) { + console.error(`Error deleting file: ${err.message}`); + } + }); + res.send({csr: csrContent, key: keyContent}); + } + }); + } + }); + } + }); +}); + + +app.post('/write_cert', (req, res) => { + let extension = 'crt', + fsMode = 'writeFile', + filename = "client_cert", + filePath = `${path.join(folderPath, filename)}.${extension}`, + options = {encoding: 'binary'}; + fs[fsMode](filePath, req.body.cert, options, (err) => { + if (err) { + console.log(err); + res.send('Error'); + } + }); + extension = 'key'; + filename = "client_key"; + filePath = `${path.join(folderPath, filename)}.${extension}`; + fs[fsMode](filePath, req.body.key, options, (err) => { + if (err) { + console.log(err); + res.send('Error'); + } + else { + res.send('Success'); + } + }); +}); + +app.post('/write_ca', (req, res) => { + let extension = 'pem', + fsMode = 'writeFile', + filename = "ca_cert", + filePath = `${path.join(folderPath, filename)}.${extension}`, + options = {encoding: 'binary'}; + fs[fsMode](filePath, req.body.ca_root, options, (err) => { + if (err) { + console.log(err); + res.send('Error'); + } + else { + res.send('Success'); + } + }); +}); + +app.listen(3000, () => { + console.log('ResponsesToFile App is listening now! Send them requests my way!'); + console.log(`Data is being stored at location: ${path.join(process.cwd(), folderPath)}`); +}); \ No newline at end of file diff --git a/docs/testing_with_robot/README.md b/docs/testing_with_robot/README.md new file mode 100644 index 0000000..71504c1 --- /dev/null +++ b/docs/testing_with_robot/README.md @@ -0,0 +1,74 @@ +[**[Return To Main]**] +# Testing With Robot Framework + +- [Testing With Robot Framework](#testing-with-robot-framework) + - [Steps to Test](#steps-to-test) + - [Script Test Execution](#script-test-execution) + - [Manual Build And Test Execution](#manual-build-and-test-execution) + - [Test result review](#test-result-review) + +## Steps to Test + +To run any test locally you will need *docker* and *docker-compose* installed in order run services and execute test plan. Steps will be: +* **Run All Services**: See section [Run All CAPIF Services](../../README.md#run-all-capif-services-locally-with-docker-images) +* **Run desired tests**: At this point we have 2 options: + * **Using helper script**: [Script Test Execution](#script-test-execution) + * **Build robot docker image and execute manually robot docker**: [Manual Build And Test Execution](#manual-build-and-test-execution) + + +## Script Test Execution +This script will build robot docker image if it's need and execute tests selected by "include" option. Just go to service folder, execute and follow steps. +``` +./runCapifTests.sh --include +``` +Results will be stored at /results + +Please check parameters (include) under *Test Execution* at [Manual Build And Test Execution](#manual-build-and-test-execution). + +## Manual Build And Test Execution + +* **Build Robot docker image**: +``` +cd tools/robot +docker build . -t 5gnow-robot-test:latest +``` + +* **Tests Execution**: + +Execute all tests locally: +``` +=path in local machine to repository cloned. +=path to a folder on local machine to store results of Robot Framework execution. +=Is the hostname set when run.sh is executed, by default it will be capifcore. +=This is the port to reach when robot framework want to reach CAPIF deployment using http, this should be set to port without TLS set on Nginx, 8080 by default. + +To execute all tests run : +docker run -ti --rm --network="host" -v /tests:/opt/robot-tests/tests -v :/opt/robot-tests/results 5gnow-robot-test:latest --variable CAPIF_HOSTNAME:capifcore --variable CAPIF_HTTP_PORT:8080 --include all +``` + +Execute specific tests locally: +``` +To run more specific tests, for example, only one functionality: +=Select one from list: + "capif_api_discover_service", + "capif_api_invoker_management", + "capif_api_publish_service", + "capif_api_events", + "capif_security_api + +And Run: +docker run -ti --rm --network="host" -v /tests:/opt/robot-tests/tests -v :/opt/robot-tests/results 5gnow-robot-test:latest --variable CAPIF_HOSTNAME:capifcore --variable CAPIF_HTTP_PORT:8080 --include +``` + +## Test result review + +In order to Review results after tests, you can check general report at /report.html or if you need more detailed information /log.html, example: +* Report: +![Report](../images/robot_report_example.png) +* Detailed information: +![Log](../images/robot_log_example.png) + +**NOTE: If you need more detail at Robot Framework Logs you can set log level option just adding to command --loglevel DEBUG** + + +[Return To Main]: ../../README.md#robot-framework \ No newline at end of file diff --git a/helm/README-vault.md b/helm/README-vault.md new file mode 100644 index 0000000..0fab958 --- /dev/null +++ b/helm/README-vault.md @@ -0,0 +1,52 @@ +# Install vault +``` +$ helm repo add hashicorp https://helm.releases.hashicorp.com +$ helm upgrade --install vault hashicorp/vault -n mon --set server.standalone.enabled=true --create-namespace + +# if you are using ingress controller, please use: +$ helm upgrade --install vault hashicorp/vault -n mon --set server.ingress.enabled=true --set server.ingress.hosts[0].host="vault.mon.int" --set server.ingress.ingressClassName=nginx --set server.standalone.enabled=true --create-namespace + +# verify pods are running +$ kubectl -n mon get pods + +``` +NOTA: If using ingressRoute. Please, create a file with: + +``` +--- + +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: vault-ingress-route + namespace: mon +spec: + entryPoints: [web] + routes: + - kind: Rule + match: Host(`vault.mon.int`) + services: + - kind: Service + name: vault-internal + port: 8200 + scheme: http + +``` +``` +# deploy ingress route + +$ kubectl apply -f ingress-route.yaml +``` +# Creating vault PKI and certificates + +## Considerations: + - If you change values by default in the `capi/values.yaml`. Please, consider have a look of some topics: + - You will need to create PKI and certificates, therefore. The `VAULT_TOKEN` provided must have sufficient permissions in Vault to create it + - Modify: + - `namespace` in `vault-job/vault-job.yaml`. The namespace should be changed in the entire file. By default is `mon` (same namespace when capif is deployed) + - `export VAULT_ADDR` using the service deployed to vault. By default is `http://vault-internal:8200` + - `export VAULT_TOKEN` using the token created to vault. By default is `dev-only-token` + - `DOMAIN1` - variable used for generate certificate (CSR) to capif `(ex: DOMAIN1=capif.mobile.cloud)`. +``` +$ kubectl apply -f vault-job/ +``` \ No newline at end of file diff --git a/helm/README.md b/helm/README.md new file mode 100644 index 0000000..3fd0ff3 --- /dev/null +++ b/helm/README.md @@ -0,0 +1,47 @@ +# Install CAPIF in Kubernetes using HELM + +## Dependencies +- Helm +- `Ingress` already in cluster (if configured in capif - `values.yaml`) + - ``` + # OPTIONAL - if not exists Ingress in cluster, use this command to install it + $ helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --set rbac.create=true --set controller.service.type=NodePort + + # OPTIONAL - if you need specify the nodePort in cluster use + $ helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --set rbac.create=true --set controller.service.type=NodePort --set controller.service.nodePorts.http=32080 --set controller.service.nodePorts.https=32443 --namespace ingress-nginx --create-namespace --set controller.extraArgs."enable-ssl-passthrough=true" --kubeconfig ../oneke-new.kubeconfig + + # Check if ssl-passthrough is enabled in nginx controller. + $ kubectl -n ingress-nginx get deploy -o yaml | grep passthrough + ``` +- `PersistentVolumeClain` already in cluster (if configured in capif) + +## Considerations before to install/deploy: +- **Prometheus**: + - You can install prometheus but you will need permissions to deploy prometheus in the cluster. The helm creates a ClusterRole to access to all resources in the cluster. + - If you don't have permission or there is already provided a Prometheus + in the cluster. in `capif/values.yaml` gives the field `monitoring.prometheus.enable: ""` + - Grafana will need the endpoint to prometheus. Please keep in mind setup the grafana's field in `capif/values.yaml` +- **Vault**: + - You will need a instance of vault already deployed. If the cluster doesn't provide the vault instance. You can install it following the next [steps](https://github.com/Telefonica/CAPIF_Future_Network_Lab/blob/main/helm/README-vault.md) + - Once the vault is provided in the cluster. You need to create the PKI and certificates. Follow the vault-job [step](https://github.com/Telefonica/CAPIF_Future_Network_Lab/blob/main/helm/README-vault.md#creating-vault-pki-and-certificates) to create it + - Setup the `parametersVault.env.VaultHostname`: This is the endPoint to vault. This endpoint can be a service/ingress of kubernetes + - Setup `parametersVault.env.VaultPort`: This is the port listenting to vault instance + - Setup `parametersVault.env.vaultAccessToken`: This is the token used for capif to create the certificates in vault. If vault owns of you. Use the token created in [Vault readme](https://github.com/Telefonica/CAPIF_Future_Network_Lab/blob/main/helm/README-vault.md#creating-vault-pki-and-certificates) . Otherwise, the admin + of the cluster will provide you the token. This token will need sufficient permissions to create PKI and certificates. +- **CAPIF** + - Please, have a look of [`values.yaml`](https://github.com/Telefonica/CAPIF_Future_Network_Lab/blob/main/helm/capif/values.yaml) file and setup according to the conditions + ``` + # download dependencies + $ helm dependency build capif/ + +# check ingress_ip.oneke +kubectl get svc -A | grep nginx + +# install capif +$ helm upgrade --install -n mon monitoring-capif capif/ --set nginx.nginx.env.capifHostname=mon-capif.monitoring.int --set ingress_ip.oneke="10.17.173.127" --atomic --create-namespace + ``` + +NOTA: The deployment can take until 8 minutes to be ready. Please, if it fails, re-install CAPIF + +## Troubleshooting +- [`Mongo stuck`](https://www.ibm.com/docs/en/cloud-paks/cp-biz-automation/20.0.x?topic=troubleshooting-mongodb-pod-fails-start-container-exit-code-14-100) \ No newline at end of file diff --git a/helm/capif/.helmignore b/helm/capif/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/helm/capif/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/Chart.yaml b/helm/capif/Chart.yaml new file mode 100644 index 0000000..625f958 --- /dev/null +++ b/helm/capif/Chart.yaml @@ -0,0 +1,26 @@ +apiVersion: v2 +name: capif +description: A Helm chart to CAPIF in Kubernetes +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: v3.1.4 +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "v3.1.4" +dependencies: + - name: "tempo" + condition: tempo.enabled + repository: "https://grafana.github.io/helm-charts" + version: "^1.3.1" diff --git a/helm/capif/README.md b/helm/capif/README.md new file mode 100644 index 0000000..a78b060 --- /dev/null +++ b/helm/capif/README.md @@ -0,0 +1,304 @@ +# Helm of CAPIF + +![Version: v1.0.0](https://img.shields.io/badge/Version-v1.0.0-informational?style=for-the-badge) +![Type: application](https://img.shields.io/badge/Type-application-informational?style=for-the-badge) +![AppVersion: v1.0.0](https://img.shields.io/badge/AppVersion-v1.0.0-informational?style=for-the-badge) + +## Description + +A Helm chart to CAPIF in Kubernetes + +## Usage + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| CapifClient.enable | string | `"true"` | If enable capif client. | +| CapifClient.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| CapifClient.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/client"` | The docker image repository to use | +| CapifClient.image.tag | string | `""` | The docker image tag to use @default Chart version | +| CapifClient.ports[0].name | string | `"8080"` | | +| CapifClient.ports[0].port | int | `8080` | | +| CapifClient.ports[0].targetPort | int | `8080` | | +| CapifClient.replicas | int | `1` | | +| CapifClient.resources.limits.cpu | string | `"100m"` | | +| CapifClient.resources.limits.memory | string | `"128Mi"` | | +| CapifClient.resources.requests.cpu | string | `"100m"` | | +| CapifClient.resources.requests.memory | string | `"128Mi"` | | +| CapifClient.type | string | `"ClusterIP"` | | +| accessControlPolicy.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| accessControlPolicy.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| accessControlPolicy.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/access-control-policy"` | The docker image repository to use | +| accessControlPolicy.image.tag | string | `""` | The docker image tag to use @default Chart version | +| accessControlPolicy.ports[0].name | string | `"8080"` | | +| accessControlPolicy.ports[0].port | int | `8080` | | +| accessControlPolicy.ports[0].targetPort | int | `8080` | | +| accessControlPolicy.replicas | int | `1` | | +| accessControlPolicy.resources.limits.cpu | string | `"100m"` | | +| accessControlPolicy.resources.limits.memory | string | `"128Mi"` | | +| accessControlPolicy.resources.requests.cpu | string | `"100m"` | | +| accessControlPolicy.resources.requests.memory | string | `"128Mi"` | | +| accessControlPolicy.type | string | `"ClusterIP"` | | +| apiInvocationLogs.apiInvocationLogs.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| apiInvocationLogs.apiInvocationLogs.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| apiInvocationLogs.apiInvocationLogs.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/api-invocation-logs-api"` | The docker image repository to use | +| apiInvocationLogs.apiInvocationLogs.image.tag | string | `""` | The docker image tag to use @default Chart version | +| apiInvocationLogs.apiInvocationLogs.resources.limits.cpu | string | `"100m"` | | +| apiInvocationLogs.apiInvocationLogs.resources.limits.memory | string | `"128Mi"` | | +| apiInvocationLogs.apiInvocationLogs.resources.requests.cpu | string | `"100m"` | | +| apiInvocationLogs.apiInvocationLogs.resources.requests.memory | string | `"128Mi"` | | +| apiInvocationLogs.ports[0].name | string | `"8080"` | | +| apiInvocationLogs.ports[0].port | int | `8080` | | +| apiInvocationLogs.ports[0].targetPort | int | `8080` | | +| apiInvocationLogs.replicas | int | `1` | | +| apiInvocationLogs.type | string | `"ClusterIP"` | | +| apiInvokerManagement.apiInvokerManagement.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| apiInvokerManagement.apiInvokerManagement.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| apiInvokerManagement.apiInvokerManagement.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/api-invoker-management-api"` | The docker image repository to use | +| apiInvokerManagement.apiInvokerManagement.image.tag | string | `""` | The docker image tag to use @default Chart version | +| apiInvokerManagement.apiInvokerManagement.resources.limits.cpu | string | `"100m"` | | +| apiInvokerManagement.apiInvokerManagement.resources.limits.memory | string | `"128Mi"` | | +| apiInvokerManagement.apiInvokerManagement.resources.requests.cpu | string | `"100m"` | | +| apiInvokerManagement.apiInvokerManagement.resources.requests.memory | string | `"128Mi"` | | +| apiInvokerManagement.ports[0].name | string | `"8080"` | | +| apiInvokerManagement.ports[0].port | int | `8080` | | +| apiInvokerManagement.ports[0].targetPort | int | `8080` | | +| apiInvokerManagement.replicas | int | `1` | | +| apiInvokerManagement.type | string | `"ClusterIP"` | | +| apiProviderManagement.apiProviderManagement.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| apiProviderManagement.apiProviderManagement.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| apiProviderManagement.apiProviderManagement.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/api-provider-management-api"` | The docker image repository to use | +| apiProviderManagement.apiProviderManagement.image.tag | string | `""` | The docker image tag to use @default Chart version | +| apiProviderManagement.apiProviderManagement.resources.limits.cpu | string | `"100m"` | | +| apiProviderManagement.apiProviderManagement.resources.limits.memory | string | `"128Mi"` | | +| apiProviderManagement.apiProviderManagement.resources.requests.cpu | string | `"100m"` | | +| apiProviderManagement.apiProviderManagement.resources.requests.memory | string | `"128Mi"` | | +| apiProviderManagement.ports[0].name | string | `"8080"` | | +| apiProviderManagement.ports[0].port | int | `8080` | | +| apiProviderManagement.ports[0].targetPort | int | `8080` | | +| apiProviderManagement.replicas | int | `1` | | +| apiProviderManagement.type | string | `"ClusterIP"` | | +| capifEvents.capifEvents.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| capifEvents.capifEvents.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| capifEvents.capifEvents.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/events-api"` | The docker image repository to use | +| capifEvents.capifEvents.image.tag | string | `""` | The docker image tag to use @default Chart version | +| capifEvents.capifEvents.resources.limits.cpu | string | `"100m"` | | +| capifEvents.capifEvents.resources.limits.memory | string | `"128Mi"` | | +| capifEvents.capifEvents.resources.requests.cpu | string | `"100m"` | | +| capifEvents.capifEvents.resources.requests.memory | string | `"128Mi"` | | +| capifEvents.ports[0].name | string | `"8080"` | | +| capifEvents.ports[0].port | int | `8080` | | +| capifEvents.ports[0].targetPort | int | `8080` | | +| capifEvents.replicas | int | `1` | | +| capifEvents.type | string | `"ClusterIP"` | | +| capifRoutingInfo.capifRoutingInfo.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| capifRoutingInfo.capifRoutingInfo.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| capifRoutingInfo.capifRoutingInfo.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/routing-info-api"` | The docker image repository to use | +| capifRoutingInfo.capifRoutingInfo.image.tag | string | `""` | The docker image tag to use @default Chart version | +| capifRoutingInfo.capifRoutingInfo.resources.limits.cpu | string | `"100m"` | | +| capifRoutingInfo.capifRoutingInfo.resources.limits.memory | string | `"128Mi"` | | +| capifRoutingInfo.capifRoutingInfo.resources.requests.cpu | string | `"100m"` | | +| capifRoutingInfo.capifRoutingInfo.resources.requests.memory | string | `"128Mi"` | | +| capifRoutingInfo.ports[0].name | string | `"8080"` | | +| capifRoutingInfo.ports[0].port | int | `8080` | | +| capifRoutingInfo.ports[0].targetPort | int | `8080` | | +| capifRoutingInfo.replicas | int | `1` | | +| capifRoutingInfo.type | string | `"ClusterIP"` | | +| capifSecurity.capifSecurity.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| capifSecurity.capifSecurity.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| capifSecurity.capifSecurity.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/security-api"` | The docker image repository to use | +| capifSecurity.capifSecurity.image.tag | string | `""` | The docker image tag to use @default Chart version | +| capifSecurity.capifSecurity.resources.limits.cpu | string | `"100m"` | | +| capifSecurity.capifSecurity.resources.limits.memory | string | `"128Mi"` | | +| capifSecurity.capifSecurity.resources.requests.cpu | string | `"100m"` | | +| capifSecurity.capifSecurity.resources.requests.memory | string | `"128Mi"` | | +| capifSecurity.ports[0].name | string | `"8080"` | | +| capifSecurity.ports[0].port | int | `8080` | | +| capifSecurity.ports[0].targetPort | int | `8080` | | +| capifSecurity.replicas | int | `1` | | +| capifSecurity.type | string | `"ClusterIP"` | | +| env | string | `""` | The Environment variable. Use openshift if you are deploying in Openshift cluster. anotherwise use the field empty | +| ingress.ip | string | `"10.17.173.127"` | | +| kubernetesClusterDomain | string | `"cluster.local"` | | +| logs.enable | string | `"true"` | If register enabled. enable: true, enable: "" = not enabled | +| logs.logs.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| logs.logs.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| logs.logs.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/auditing-api"` | The docker image repository to use | +| logs.logs.image.tag | string | `""` | The docker image tag to use @default Chart version | +| logs.logs.resources.limits.cpu | string | `"100m"` | | +| logs.logs.resources.limits.memory | string | `"128Mi"` | | +| logs.logs.resources.requests.cpu | string | `"100m"` | | +| logs.logs.resources.requests.memory | string | `"128Mi"` | | +| logs.ports[0].name | string | `"8080"` | | +| logs.ports[0].port | int | `8080` | | +| logs.ports[0].targetPort | int | `8080` | | +| logs.replicas | int | `1` | | +| logs.type | string | `"ClusterIP"` | | +| mongo.mongo.env.mongoInitdbRootPassword | string | `"example"` | | +| mongo.mongo.env.mongoInitdbRootUsername | string | `"root"` | | +| mongo.mongo.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| mongo.mongo.image.repository | string | `"mongo"` | The docker image repository to use | +| mongo.mongo.image.tag | string | `"6.0.2"` | The docker image tag to use @default Chart version | +| mongo.mongo.resources | object | `{}` | | +| mongo.persistence | object | `{"enable":"true","storage":"8Gi"}` | If mongo.persistence enabled. enable: true, enable: "" = not enabled | +| mongo.ports[0].name | string | `"27017"` | | +| mongo.ports[0].port | int | `27017` | | +| mongo.ports[0].targetPort | int | `27017` | | +| mongo.replicas | int | `1` | | +| mongo.type | string | `"ClusterIP"` | | +| mongoExpress.mongoExpress.env.meConfigMongodbAdminpassword | string | `"example"` | | +| mongoExpress.mongoExpress.env.meConfigMongodbAdminusername | string | `"root"` | | +| mongoExpress.mongoExpress.env.meConfigMongodbUrl | string | `"mongodb://root:example@mongo:27017/"` | | +| mongoExpress.mongoExpress.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| mongoExpress.mongoExpress.image.repository | string | `"mongo-express"` | The docker image repository to use | +| mongoExpress.mongoExpress.image.tag | string | `"1.0.0-alpha.4"` | The docker image tag to use @default Chart version | +| mongoExpress.mongoExpress.resources.limits.cpu | string | `"100m"` | | +| mongoExpress.mongoExpress.resources.limits.memory | string | `"128Mi"` | | +| mongoExpress.mongoExpress.resources.requests.cpu | string | `"100m"` | | +| mongoExpress.mongoExpress.resources.requests.memory | string | `"128Mi"` | | +| mongoExpress.ports[0].name | string | `"8082"` | | +| mongoExpress.ports[0].port | int | `8082` | | +| mongoExpress.ports[0].targetPort | int | `8081` | | +| mongoExpress.replicas | int | `1` | | +| mongoExpress.type | string | `"ClusterIP"` | | +| mongoRegister.mongo.env.mongoInitdbRootPassword | string | `"example"` | | +| mongoRegister.mongo.env.mongoInitdbRootUsername | string | `"root"` | | +| mongoRegister.mongo.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| mongoRegister.mongo.image.repository | string | `"mongo"` | The docker image repository to use | +| mongoRegister.mongo.image.tag | string | `"6.0.2"` | The docker image tag to use @default Chart version | +| mongoRegister.mongo.resources | object | `{}` | | +| mongoRegister.ports[0].name | string | `"27017"` | | +| mongoRegister.ports[0].port | int | `27017` | | +| mongoRegister.ports[0].targetPort | int | `27017` | | +| mongoRegister.replicas | int | `1` | | +| mongoRegister.type | string | `"ClusterIP"` | | +| monitoring.enable | string | `"true"` | | +| monitoring.enable | string | `"true"` | If monitoring enabled. enable: true, enable: "" = not enabled | +| monitoring.fluentBit.env.lokiUrl | string | `"http://loki:3100/loki/api/v1/push"` | | +| monitoring.fluentBit.image.repository | string | `"grafana/fluent-bit-plugin-loki"` | The docker image repository to use | +| monitoring.fluentBit.image.tag | string | `"latest"` | The docker image tag to use @default Chart version | +| monitoring.fluentBit.resources | object | `{}` | | +| monitoring.grafana.env.gfAuthAnonymousEnable | bool | `true` | | +| monitoring.grafana.env.gfAuthAnonymousOrgRole | string | `"Admin"` | | +| monitoring.grafana.env.gfSecurityAdminPassword | string | `"secure_pass"` | | +| monitoring.grafana.env.gfSecurityAllowEmbedding | bool | `true` | | +| monitoring.grafana.env.lokiUrl | string | `"http://loki:3100"` | | +| monitoring.grafana.env.prometheusUrl | string | `"http://prometheus.mon.svc.cluster.local:9090"` | | +| monitoring.grafana.env.tempoUrl | string | `"http://monitoring-capif-tempo:3100"` | | +| monitoring.grafana.image.repository | string | `"grafana/grafana"` | The docker image repository to use | +| monitoring.grafana.image.tag | string | `"latest"` | The docker image tag to use @default Chart version | +| monitoring.grafana.ingress | object | `{"annotations":null,"enabled":true,"hosts":[{"host":"grafana.5gnacar.int","paths":[{"path":"/","pathType":"Prefix"}]}],"ingressClassName":"nginx","tls":[]}` | If ingress enabled=true, use monitoring.grafana.ingressRoute.enable="" | +| monitoring.grafana.ingressRoute | object | `{"enable":"","host":"grafana.5gnacar.int"}` | If ingressRoute enable=true, use monitoring.grafana.ingress.enabled="" | +| monitoring.grafana.persistence | object | `{"enable":"true","storage":"100Mi"}` | If grafana.persistence enabled. enable: true, enable: "" = not enabled | +| monitoring.grafana.resources | object | `{}` | | +| monitoring.grafana.service.port | int | `3000` | | +| monitoring.grafana.service.type | string | `"ClusterIP"` | | +| monitoring.loki.image.repository | string | `"grafana/loki"` | The docker image repository to use | +| monitoring.loki.image.tag | string | `"2.8.0"` | The docker image tag to use @default Chart version | +| monitoring.loki.persistence | object | `{"enable":"true","storage":"100Mi"}` | If grafana.persistence enabled. enable: true, enable: "" = not enabled | +| monitoring.loki.resources | object | `{}` | | +| monitoring.otel.configMap.tempoEndpoint | string | `"monitoring-capif-tempo:4317"` | | +| monitoring.otel.image.repository | string | `"otel/opentelemetry-collector"` | The docker image repository to use | +| monitoring.otel.image.tag | string | `"0.81.0"` | The docker image tag to use @default Chart version | +| monitoring.otel.resources | object | `{}` | | +| monitoring.prometheus.enable | string | `"true"` | It will deploy prometheus | +| monitoring.prometheus.image.repository | string | `"prom/prometheus"` | The docker image repository to use | +| monitoring.prometheus.image.tag | string | `"latest"` | The docker image tag to use @default Chart version | +| monitoring.prometheus.ingress.annotations | string | `nil` | | +| monitoring.prometheus.ingress.enabled | bool | `true` | | +| monitoring.prometheus.ingress.hosts[0].host | string | `"prometheus.5gnacar.int"` | | +| monitoring.prometheus.ingress.hosts[0].paths[0].path | string | `"/"` | | +| monitoring.prometheus.ingress.hosts[0].paths[0].pathType | string | `"Prefix"` | | +| monitoring.prometheus.ingress.ingressClassName | string | `"nginx"` | | +| monitoring.prometheus.ingress.tls | list | `[]` | | +| monitoring.prometheus.ingressRoute | object | `{"enable":"","host":"prometheus.5gnacar.int"}` | If ingressRoute enable=true, use monitoring.prometheus.ingress.enabled="" | +| monitoring.prometheus.persistence.enable | string | `"true"` | | +| monitoring.prometheus.persistence.storage | string | `"8Gi"` | | +| monitoring.prometheus.resources | object | `{}` | | +| monitoring.prometheus.service.port | int | `9090` | | +| monitoring.prometheus.service.type | string | `"ClusterIP"` | | +| monitoring.renderer.env.enableMetrics | string | `"true"` | | +| monitoring.renderer.image.repository | string | `"grafana/grafana-image-renderer"` | The docker image repository to use | +| monitoring.renderer.image.tag | string | `"latest"` | The docker image tag to use @default Chart version | +| monitoring.renderer.resources | object | `{}` | | +| nginx.annotations."nginx.ingress.kubernetes.io/backend-protocol" | string | `"HTTPS"` | | +| nginx.annotations."nginx.ingress.kubernetes.io/ssl-passthrough" | string | `"true"` | | +| nginx.annotations."nginx.ingress.kubernetes.io/ssl-redirect" | string | `"true"` | | +| nginx.ingressClassName | string | `"nginx"` | | +| nginx.ingressType | string | `"Ingress"` | if nginx.ingressType: "Ingress". set up monitoring.prometheus.ingress: true and monitoring.grafana.ingress: true Use IngressRoute if you want to use Gateway API. ex traefix | +| nginx.nginx.env.capifHostname | string | `"my-capif.apps.ocp-epg.hi.inet"` | Ingress's host to Capif | +| nginx.nginx.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| nginx.nginx.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/nginx"` | The docker image repository to use | +| nginx.nginx.image.tag | string | `""` | The docker image tag to use @default Chart version | +| nginx.nginx.resources.limits.cpu | string | `"100m"` | | +| nginx.nginx.resources.limits.memory | string | `"128Mi"` | | +| nginx.nginx.resources.requests.cpu | string | `"100m"` | | +| nginx.nginx.resources.requests.memory | string | `"128Mi"` | | +| nginx.ports[0].name | string | `"8080"` | | +| nginx.ports[0].port | int | `8080` | | +| nginx.ports[0].targetPort | int | `8080` | | +| nginx.ports[1].name | string | `"443"` | | +| nginx.ports[1].port | int | `443` | | +| nginx.ports[1].targetPort | int | `443` | | +| nginx.replicas | int | `1` | | +| nginx.type | string | `"ClusterIP"` | | +| parametersVault.env.vaultAccessToken | string | `"dev-only-token"` | | +| parametersVault.env.vaultHostname | string | `"vault-internal.mon.svc.cluster.local"` | | +| parametersVault.env.vaultPort | int | `8200` | | +| publishedApis.ports[0].name | string | `"8080"` | | +| publishedApis.ports[0].port | int | `8080` | | +| publishedApis.ports[0].targetPort | int | `8080` | | +| publishedApis.publishedApis.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| publishedApis.publishedApis.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| publishedApis.publishedApis.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/publish-service-api"` | The docker image repository to use | +| publishedApis.publishedApis.image.tag | string | `""` | The docker image tag to use @default Chart version | +| publishedApis.publishedApis.resources.limits.cpu | string | `"100m"` | | +| publishedApis.publishedApis.resources.limits.memory | string | `"128Mi"` | | +| publishedApis.publishedApis.resources.requests.cpu | string | `"100m"` | | +| publishedApis.publishedApis.resources.requests.memory | string | `"128Mi"` | | +| publishedApis.replicas | int | `1` | | +| publishedApis.type | string | `"ClusterIP"` | | +| redis.ports[0].name | string | `"6379"` | | +| redis.ports[0].port | int | `6379` | | +| redis.ports[0].targetPort | int | `6379` | | +| redis.redis.env.redisReplicationMode | string | `"master"` | | +| redis.redis.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| redis.redis.image.repository | string | `"redis"` | The docker image repository to use | +| redis.redis.image.tag | string | `"alpine"` | The docker image tag to use @default Chart version | +| redis.redis.resources.limits.cpu | string | `"100m"` | | +| redis.redis.resources.limits.memory | string | `"128Mi"` | | +| redis.redis.resources.requests.cpu | string | `"100m"` | | +| redis.redis.resources.requests.memory | string | `"128Mi"` | | +| redis.replicas | int | `1` | | +| redis.type | string | `"ClusterIP"` | | +| register.enable | string | `"true"` | If register enabled. enable: true, enable: "" = not enabled | +| register.ports[0].name | string | `"8080"` | | +| register.ports[0].port | int | `8084` | | +| register.ports[0].targetPort | int | `8080` | | +| register.register.env.mongoHost | string | `"mongo-register"` | | +| register.register.env.mongoPort | int | `27017` | | +| register.register.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| register.register.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/jwtauth"` | The docker image repository to use | +| register.register.image.tag | string | `""` | The docker image tag to use @default Chart version | +| register.register.resources.limits.cpu | string | `"100m"` | | +| register.register.resources.limits.memory | string | `"128Mi"` | | +| register.register.resources.requests.cpu | string | `"100m"` | | +| register.register.resources.requests.memory | string | `"128Mi"` | | +| register.replicas | int | `1` | | +| register.type | string | `"ClusterIP"` | | +| serviceApis.ports[0].name | string | `"8080"` | | +| serviceApis.ports[0].port | int | `8080` | | +| serviceApis.ports[0].targetPort | int | `8080` | | +| serviceApis.replicas | int | `1` | | +| serviceApis.serviceApis.env | object | `{"monitoring":"true"}` | If env.monitoring: true. Setup monitoring.enable: true | +| serviceApis.serviceApis.image.imagePullPolicy | string | `"Always"` | Image pull policy: Always, IfNotPresent | +| serviceApis.serviceApis.image.repository | string | `"public.ecr.aws/o2v4a8t6/opencapif/discover-service-api"` | The docker image repository to use | +| serviceApis.serviceApis.image.tag | string | `""` | The docker image tag to use @default Chart version | +| serviceApis.serviceApis.resources.limits.cpu | string | `"100m"` | | +| serviceApis.serviceApis.resources.limits.memory | string | `"128Mi"` | | +| serviceApis.serviceApis.resources.requests.cpu | string | `"100m"` | | +| serviceApis.serviceApis.resources.requests.memory | string | `"128Mi"` | | +| serviceApis.type | string | `"ClusterIP"` | | +| tempo | object | `{"enabled":true,"persistence":{"enabled":true,"size":"3Gi"},"tempo":{"metricsGenerator":{"enabled":true,"remoteWriteUrl":"http://prometheus.mon.svc.cluster.local:9090/api/v1/write"}}}` | If monitoring.enable: "true". Also enable tempo.enabled: true | + diff --git a/helm/capif/docker-monitoring.json b/helm/capif/docker-monitoring.json new file mode 100644 index 0000000..8a3102a --- /dev/null +++ b/helm/capif/docker-monitoring.json @@ -0,0 +1,690 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Docker monitoring with Prometheus and cAdvisor", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 193, + "graphTooltip": 1, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 7, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "count(container_last_seen{image!=\"\"})", + "intervalFactor": 2, + "legendFormat": "", + "metric": "container_last_seen", + "refId": "A", + "step": 240 + } + ], + "title": "Running containers", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "mbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 5, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum(container_memory_usage_bytes{image!=\"\"})/1024/1024", + "intervalFactor": 2, + "legendFormat": "", + "metric": "container_memory_usage_bytes", + "refId": "A", + "step": 240 + } + ], + "title": "Total Memory Usage", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 6, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum(rate(container_cpu_user_seconds_total{image!=\"\"}[5m]) * 100)", + "intervalFactor": 2, + "legendFormat": "", + "metric": "container_memory_usage_bytes", + "refId": "A", + "step": 240 + } + ], + "title": "Total CPU Usage", + "transparent": true, + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 3 + }, + "hiddenSeries": false, + "id": 2, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "rate(container_cpu_user_seconds_total{image!=\"\"}[5m]) * 100", + "intervalFactor": 2, + "legendFormat": "{{name}}", + "metric": "cpu", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "CPU Usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 10 + }, + "hiddenSeries": false, + "id": 1, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "container_memory_usage_bytes{image!=\"\"}", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "metric": "container_memory_usage_bytes", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory Usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 17 + }, + "hiddenSeries": false, + "id": 3, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "irate(container_network_receive_bytes_total{image!=\"\"}[5m])", + "intervalFactor": 2, + "legendFormat": "{{name}}", + "metric": "container_network_receive_bytes_total", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Network Rx", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 17 + }, + "hiddenSeries": false, + "id": 4, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.5.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "irate(container_network_transmit_bytes_total{image!=\"\"}[5m])", + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "A", + "step": 20 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Network Tx", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + } + ], + "refresh": "10s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "docker" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Docker monitoring", + "uid": "f66dea48-ca2f-46fb-a6f0-50bf50502d74", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/helm/capif/kubernetes-dashboard.json b/helm/capif/kubernetes-dashboard.json new file mode 100644 index 0000000..ac97f80 --- /dev/null +++ b/helm/capif/kubernetes-dashboard.json @@ -0,0 +1,2629 @@ +{ + "annotations": { + "list": [ + { + "$$hashKey": "object:103", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Monitors Kubernetes cluster using Prometheus. Shows overall cluster CPU / Memory / Filesystem usage as well as individual pod, containers, systemd services statistics. Uses cAdvisor metrics only.", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12740, + "graphTooltip": 0, + "id": 7, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 33, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Network I/O pressure", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 1 + }, + "height": "200px", + "hiddenSeries": false, + "id": 32, + "legend": { + "alignAsTable": false, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{kubernetes_io_hostname=~\"^$Node$\"}[1m]))", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "Received", + "metric": "network", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{kubernetes_io_hostname=~\"^$Node$\"}[1m]))", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "Sent", + "metric": "network", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Network I/O pressure", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "Bps", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 34, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Total usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 65 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 4, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) / sum (machine_memory_bytes{kubernetes_io_hostname=~\"^$Node$\"}) * 100", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Cluster memory usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 65 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 6, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) / sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"}) * 100", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Cluster CPU usage (1m avg)", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 65 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 7, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) / sum (container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) * 100", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "", + "metric": "", + "refId": "A", + "step": 10 + } + ], + "title": "Cluster filesystem usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 13 + }, + "id": 9, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Used", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 4, + "y": 13 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (machine_memory_bytes{kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 8, + "y": 13 + }, + "id": 11, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m]))", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Used", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 12, + "y": 13 + }, + "id": 12, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 16, + "y": 13 + }, + "id": 13, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Used", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 13 + }, + "id": 14, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Total", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 35, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Pods CPU usage", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 17 + }, + "height": "", + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "metric": "container_cpu", + "range": true, + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:112", + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:113", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 39, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Pods memory usage", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 25 + }, + "hiddenSeries": false, + "id": 25, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (container_memory_working_set_bytes{image!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "metric": "container_memory_usage:sort_desc", + "range": true, + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:181", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:182", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 43, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Pods network I/O", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 33 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> {{ pod }}", + "metric": "network", + "range": true, + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (pod)", + "hide": true, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- {{ pod }}", + "metric": "network", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods network I/O (1m avg)", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 37, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 41 + }, + "height": "", + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",name=~\"^k8s_.*\",container!=\"POD\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (container, pod)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "pod: {{ pod }}| {{ container }}", + "metric": "container_cpu", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, name, image)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "container_cpu", + "refId": "B", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "container_cpu", + "refId": "C", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Containers CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:337", + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:338", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Containers CPU usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 41, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 42 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{image!=\"\",name=~\"^k8s_.*\",container!=\"POD\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (container, pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "pod: {{ pod }} | {{ container }}", + "metric": "container_memory_usage:sort_desc", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (kubernetes_io_hostname, name, image)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "container_memory_usage:sort_desc", + "refId": "B", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (kubernetes_io_hostname, rkt_container_name)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "container_memory_usage:sort_desc", + "refId": "C", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Containers memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:406", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:407", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Containers memory usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 44, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (container, pod)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> pod: {{ pod }} | {{ container }}", + "metric": "network", + "refId": "B", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (container, pod)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- pod: {{ pod }} | {{ container }}", + "metric": "network", + "refId": "D", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, name, image)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "network", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, name, image)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "network", + "refId": "C", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_transmit_bytes_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "network", + "refId": "E", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "network", + "refId": "F", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Containers network I/O (1m avg)", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Containers network I/O", + "type": "row" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 43 + }, + "id": 36, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "System services CPU usage", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 44 + }, + "height": "", + "hiddenSeries": false, + "id": 23, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (rate (container_cpu_usage_seconds_total{systemd_service_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (systemd_service_name)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ systemd_service_name }}", + "metric": "container_cpu", + "range": true, + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "System services CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 51 + }, + "id": 40, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 29 + }, + "hiddenSeries": false, + "id": 26, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{systemd_service_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}) by (systemd_service_name)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ systemd_service_name }}", + "metric": "container_memory_usage:sort_desc", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "System services memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "System services memory usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 38, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 46 + }, + "hiddenSeries": false, + "id": 20, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ id }}", + "metric": "container_cpu", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "All processes CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:254", + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:255", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "All processes CPU usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 53 + }, + "id": 42, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 47 + }, + "hiddenSeries": false, + "id": 28, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) by (id)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ id }}", + "metric": "container_memory_usage:sort_desc", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "All processes memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "All processes memory usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 54 + }, + "id": 45, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "id": 29, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> {{ id }}", + "metric": "network", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- {{ id }}", + "metric": "network", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "All processes network I/O (1m avg)", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "All processes network I/O", + "type": "row" + } + ], + "refresh": "10s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "kubernetes" + ], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": "monitoring", + "value": "monitoring" + }, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "definition": "label_values(namespace)", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "namespace", + "options": [], + "query": "label_values(namespace)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "definition": "", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "Node", + "options": [], + "query": "label_values(kubernetes_io_hostname)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Kubernetes Monitoring Dashboard", + "uid": "msqzbWjWk", + "version": 2, + "weekStart": "" + } \ No newline at end of file diff --git a/helm/capif/loki-logs.json b/helm/capif/loki-logs.json new file mode 100644 index 0000000..e7e4d72 --- /dev/null +++ b/helm/capif/loki-logs.json @@ -0,0 +1,281 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Simple Loki dashboard", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 13198, + "graphTooltip": 0, + "id": 9, + "links": [], + "liveNow": false, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "loki", + "uid": "$datasource" + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.5.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "count_over_time({job=\"fluent-bit\"}[1m])", + "legendFormat": "{{ container_name }}", + "queryType": "range", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Metric Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "loki", + "uid": "e4f43364-7019-45a7-aa7a-14ce2d4ddb0b" + }, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "pluginVersion": "7.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "e4f43364-7019-45a7-aa7a-14ce2d4ddb0b" + }, + "editorMode": "code", + "expr": "{job=~\"fluent-bit\"} |~ \"$string\"", + "legendFormat": "", + "queryType": "range", + "refId": "A" + } + ], + "title": "Loki Search", + "type": "logs" + } + ], + "refresh": "1m", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Loki", + "value": "Loki" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "loki", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "loki", + "uid": "$datasource" + }, + "definition": "label_values(container_name)", + "hide": 0, + "includeAll": true, + "label": "app", + "multi": false, + "name": "app", + "options": [], + "query": "label_values(container_name)", + "refresh": 2, + "regex": "(.*)-.*-.*-.*-.*-.*", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "loki", + "uid": "$datasource" + }, + "definition": "label_values(container_name)", + "hide": 0, + "includeAll": true, + "label": "job", + "multi": false, + "name": "job", + "options": [], + "query": "label_values(container_name)", + "refresh": 2, + "regex": "$app-(.*)", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "string", + "name": "string", + "options": [ + { + "selected": true, + "text": "", + "value": "" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Loki Logs", + "uid": "ffxEJdvGz", + "version": 6, + "weekStart": "" +} \ No newline at end of file diff --git a/helm/capif/templates/_helpers.tpl b/helm/capif/templates/_helpers.tpl new file mode 100644 index 0000000..35ce1ec --- /dev/null +++ b/helm/capif/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "capif.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "capif.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "capif.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "capif.labels" -}} +helm.sh/chart: {{ include "capif.chart" . }} +{{ include "capif.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "capif.selectorLabels" -}} +app.kubernetes.io/name: {{ include "capif.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "capif.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "capif.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/access-control-policy.yaml b/helm/capif/templates/access-control-policy.yaml new file mode 100644 index 0000000..8b2b198 --- /dev/null +++ b/helm/capif/templates/access-control-policy.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: access-control-policy + labels: + io.kompose.service: access-control-policy + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.accessControlPolicy.type }} + selector: + io.kompose.service: access-control-policy + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.accessControlPolicy.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/api-invocation-logs.yaml b/helm/capif/templates/api-invocation-logs.yaml new file mode 100644 index 0000000..a9b4d8f --- /dev/null +++ b/helm/capif/templates/api-invocation-logs.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-invocation-logs + labels: + io.kompose.service: api-invocation-logs + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.apiInvocationLogs.type }} + selector: + io.kompose.service: api-invocation-logs + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.apiInvocationLogs.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/api-invoker-management.yaml b/helm/capif/templates/api-invoker-management.yaml new file mode 100644 index 0000000..3eaeda4 --- /dev/null +++ b/helm/capif/templates/api-invoker-management.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-invoker-management + labels: + io.kompose.service: api-invoker-management + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.apiInvokerManagement.type }} + selector: + io.kompose.service: api-invoker-management + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.apiInvokerManagement.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/api-provider-management.yaml b/helm/capif/templates/api-provider-management.yaml new file mode 100644 index 0000000..4237986 --- /dev/null +++ b/helm/capif/templates/api-provider-management.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-provider-management + labels: + io.kompose.service: api-provider-management + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.apiProviderManagement.type }} + selector: + io.kompose.service: api-provider-management + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.apiProviderManagement.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/capif-events-configmap.yaml b/helm/capif/templates/capif-events-configmap.yaml new file mode 100644 index 0000000..ca31c23 --- /dev/null +++ b/helm/capif/templates/capif-events-configmap.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-events-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'col': 'eventsdetails', + 'certs_col': "certs", + 'capif_invokers_col': 'invokerdetails', + 'capif_providers_col': 'providerenrolmentdetails', + 'host': 'mongo', + 'port': "27017" + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } diff --git a/helm/capif/templates/capif-events.yaml b/helm/capif/templates/capif-events.yaml new file mode 100644 index 0000000..40b3d7b --- /dev/null +++ b/helm/capif/templates/capif-events.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: capif-events + labels: + io.kompose.service: capif-events + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.capifEvents.type }} + selector: + io.kompose.service: capif-events + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.capifEvents.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/capif-invocation-configmap.yaml b/helm/capif/templates/capif-invocation-configmap.yaml new file mode 100644 index 0000000..68fc1f1 --- /dev/null +++ b/helm/capif/templates/capif-invocation-configmap.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-invocation-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'logs_col': 'invocationlogs', + 'invoker_col': 'invokerdetails', + 'prov_col': 'providerenrolmentdetails', + 'serv_col': 'serviceapidescriptions', + 'capif_users_col': "user", + 'host': 'mongo', + 'port': "27017" + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } diff --git a/helm/capif/templates/capif-invoker-configmap.yaml b/helm/capif/templates/capif-invoker-configmap.yaml new file mode 100644 index 0000000..32bab3c --- /dev/null +++ b/helm/capif/templates/capif-invoker-configmap.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-invoker-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'col': 'invokerdetails', + 'capif_users_col': "user", + 'certs_col': "certs", + 'service_col': 'serviceapidescriptions', + 'host': 'mongo', + 'port': "27017" + } + mongo_register: { + 'user': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif_users', + 'col': 'user', + 'host': 'mongo-register', + 'port': '27017' + } + ca_factory: { + "url": {{ quote .Values.parametersVault.env.vaultHostname }}, + "port": {{ quote .Values.parametersVault.env.vaultPort }}, + "token": {{ quote .Values.parametersVault.env.vaultAccessToken }} + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } \ No newline at end of file diff --git a/helm/capif/templates/capif-logs-configmap.yaml b/helm/capif/templates/capif-logs-configmap.yaml new file mode 100644 index 0000000..53cae6e --- /dev/null +++ b/helm/capif/templates/capif-logs-configmap.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-logs-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'logs_col': 'invocationlogs', + 'capif_users_col': "user", + 'host': 'mongo', + 'port': "27017" + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } + diff --git a/helm/capif/templates/capif-provider-configmap.yaml b/helm/capif/templates/capif-provider-configmap.yaml new file mode 100644 index 0000000..28e530f --- /dev/null +++ b/helm/capif/templates/capif-provider-configmap.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-provider-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'col': 'providerenrolmentdetails', + 'certs_col': "certs", + 'capif_users': 'user', + 'host': 'mongo', + 'port': "27017" + } + mongo_register: { + 'user': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif_users', + 'col': 'user', + 'host': 'mongo-register', + 'port': '27017' + } + ca_factory: { + "url": {{ quote .Values.parametersVault.env.vaultHostname }}, + "port": {{ quote .Values.parametersVault.env.vaultPort }}, + "token": {{ quote .Values.parametersVault.env.vaultAccessToken }} + } + + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } \ No newline at end of file diff --git a/helm/capif/templates/capif-published-configmap.yaml b/helm/capif/templates/capif-published-configmap.yaml new file mode 100644 index 0000000..507afd4 --- /dev/null +++ b/helm/capif/templates/capif-published-configmap.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-published-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'col': 'serviceapidescriptions', + 'certs_col': "certs", + 'capif_provider_col': "providerenrolmentdetails", + 'host': 'mongo', + 'port': "27017" + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } \ No newline at end of file diff --git a/helm/capif/templates/capif-routing-info.yaml b/helm/capif/templates/capif-routing-info.yaml new file mode 100644 index 0000000..6de48aa --- /dev/null +++ b/helm/capif/templates/capif-routing-info.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: capif-routing-info + labels: + io.kompose.service: capif-routing-info + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.capifRoutingInfo.type }} + selector: + io.kompose.service: capif-routing-info + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.capifRoutingInfo.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/capif-security-configmap.yaml b/helm/capif/templates/capif-security-configmap.yaml new file mode 100644 index 0000000..ade6a59 --- /dev/null +++ b/helm/capif/templates/capif-security-configmap.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-security-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'col': 'security', + 'capif_service_col': 'serviceapidescriptions', + 'certs_col': "certs", + 'capif_invokers' : 'invokerdetails', + 'host': 'mongo', + 'port': "27017" + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } \ No newline at end of file diff --git a/helm/capif/templates/capif-security.yaml b/helm/capif/templates/capif-security.yaml new file mode 100644 index 0000000..e0bf7d8 --- /dev/null +++ b/helm/capif/templates/capif-security.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: capif-security + labels: + io.kompose.service: capif-security + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.capifSecurity.type }} + selector: + io.kompose.service: capif-security + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.capifSecurity.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/capif-service-configmap.yaml b/helm/capif/templates/capif-service-configmap.yaml new file mode 100644 index 0000000..1cd3d66 --- /dev/null +++ b/helm/capif/templates/capif-service-configmap.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-service-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'col': 'serviceapidescriptions', + 'invokers_col': 'invokerdetails', + 'capif_users_col': "user", + 'host': 'mongo', + 'port': "27017" + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } \ No newline at end of file diff --git a/helm/capif/templates/deployment.yaml b/helm/capif/templates/deployment.yaml new file mode 100644 index 0000000..4c2e026 --- /dev/null +++ b/helm/capif/templates/deployment.yaml @@ -0,0 +1,1001 @@ +{{- if eq .Values.CapifClient.enable "true" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: capif-client + labels: + io.kompose.service: capif-client + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.CapifClient.replicas }} + selector: + matchLabels: + io.kompose.service: capif-client + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: capif-client + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: CAPIF_HOSTNAME + value: nginx.mon.svc.cluster.local + - name: VAULT_HOSTNAME + value: {{ quote .Values.parametersVault.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.parametersVault.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.parametersVault.env.vaultAccessToken }} + image: {{ .Values.CapifClient.image.repository }}:{{ .Values.CapifClient.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.CapifClient.image.imagePullPolicy }} + name: capif-client + resources: + {{- toYaml .Values.CapifClient.resources | nindent 12 }} + restartPolicy: Always +{{- end }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: access-control-policy + labels: + io.kompose.service: access-control-policy + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.accessControlPolicy.replicas }} + selector: + matchLabels: + io.kompose.service: access-control-policy + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: access-control-policy + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.nginx.nginx.env.capifHostname }} + - name: MONITORING + value: {{ quote .Values.accessControlPolicy.env.monitoring }} + image: {{ .Values.accessControlPolicy.image.repository }}:{{ .Values.accessControlPolicy.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.accessControlPolicy.image.imagePullPolicy }} + name: access-control-policy + ports: + - containerPort: 8080 + resources: + {{- toYaml .Values.accessControlPolicy.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + restartPolicy: Always + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api-invocation-logs + labels: + io.kompose.service: api-invocation-logs + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.apiInvocationLogs.replicas }} + selector: + matchLabels: + io.kompose.service: api-invocation-logs + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: api-invocation-logs + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-invocation-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.nginx.nginx.env.capifHostname }} + - name: MONITORING + value: {{ quote .Values.apiInvocationLogs.apiInvocationLogs.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.parametersVault.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.parametersVault.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.parametersVault.env.vaultAccessToken }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.apiInvocationLogs.apiInvocationLogs.image.repository }}:{{ .Values.apiInvocationLogs.apiInvocationLogs.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.apiInvocationLogs.apiInvocationLogs.image.imagePullPolicy }} + name: api-invocation-logs + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-invocation-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.apiInvocationLogs.apiInvocationLogs.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + volumes: + - name: capif-invocation-config + configMap: + name: capif-invocation-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api-invoker-management + labels: + io.kompose.service: api-invoker-management + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.apiInvokerManagement.replicas }} + selector: + matchLabels: + io.kompose.service: api-invoker-management + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: api-invoker-management + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-invoker-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: MONITORING + value: {{ quote .Values.apiInvokerManagement.apiInvokerManagement.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.parametersVault.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.parametersVault.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.parametersVault.env.vaultAccessToken }} + image: {{ .Values.apiInvokerManagement.apiInvokerManagement.image.repository }}:{{ + .Values.apiInvokerManagement.apiInvokerManagement.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.apiInvokerManagement.apiInvokerManagement.image.imagePullPolicy }} + name: api-invoker-management + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-invoker-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.apiInvokerManagement.apiInvokerManagement.resources | nindent 12 }} + volumes: + - name: capif-invoker-config + configMap: + name: capif-invoker-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api-provider-management + labels: + io.kompose.service: api-provider-management + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.apiProviderManagement.replicas }} + selector: + matchLabels: + io.kompose.service: api-provider-management + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: api-provider-management + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-provider-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: MONITORING + value: {{ quote .Values.apiProviderManagement.apiProviderManagement.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.parametersVault.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.parametersVault.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.parametersVault.env.vaultAccessToken }} + image: {{ .Values.apiProviderManagement.apiProviderManagement.image.repository + }}:{{ .Values.apiProviderManagement.apiProviderManagement.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.apiProviderManagement.apiProviderManagement.image.imagePullPolicy }} + name: api-provider-management + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-provider-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.apiProviderManagement.apiProviderManagement.resources | nindent 12 }} + volumes: + - name: capif-provider-config + configMap: + name: capif-provider-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: capif-events + labels: + io.kompose.service: capif-events + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.capifEvents.replicas }} + selector: + matchLabels: + io.kompose.service: capif-events + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: capif-events + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-events-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: MONITORING + value: {{ quote .Values.capifEvents.capifEvents.env.monitoring }} + image: {{ .Values.capifEvents.capifEvents.image.repository }}:{{ .Values.capifEvents.capifEvents.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.capifEvents.capifEvents.image.imagePullPolicy }} + name: capif-events + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-events-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.capifEvents.capifEvents.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: capif-events-config + configMap: + name: capif-events-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: capif-routing-info + labels: + io.kompose.service: capif-routing-info + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.capifRoutingInfo.replicas }} + selector: + matchLabels: + io.kompose.service: capif-routing-info + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: capif-routing-info + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: MONITORING + value: {{ quote .Values.capifRoutingInfo.capifRoutingInfo.env.monitoring }} + image: {{ .Values.capifRoutingInfo.capifRoutingInfo.image.repository }}:{{ .Values.capifRoutingInfo.capifRoutingInfo.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.capifRoutingInfo.capifRoutingInfo.image.imagePullPolicy }} + name: capif-routing-info + ports: + - containerPort: 8080 + resources: + {{- toYaml .Values.capifRoutingInfo.capifRoutingInfo.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: capif-security + labels: + io.kompose.service: capif-security + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.capifSecurity.replicas }} + selector: + matchLabels: + io.kompose.service: capif-security + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: capif-security + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-security-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.nginx.nginx.env.capifHostname }} + - name: MONITORING + value: {{ quote .Values.capifSecurity.capifSecurity.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.parametersVault.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.parametersVault.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.parametersVault.env.vaultAccessToken }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.capifSecurity.capifSecurity.image.repository }}:{{ .Values.capifSecurity.capifSecurity.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.capifSecurity.capifSecurity.image.imagePullPolicy }} + name: capif-security + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-security-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.capifSecurity.capifSecurity.resources | nindent 12 }} + volumes: + - name: capif-security-config + configMap: + name: capif-security-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always + restartPolicy: Always + +{{- if eq .Values.register.enable "true" }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: register + labels: + io.kompose.service: register + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.register.replicas }} + selector: + matchLabels: + io.kompose.service: register + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: register + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/register-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.parametersVault.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.parametersVault.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.parametersVault.env.vaultAccessToken }} + image: {{ .Values.register.register.image.repository }}:{{ .Values.register.register.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.register.register.image.imagePullPolicy }} + name: register + ports: + - containerPort: 8080 + resources: + {{- toYaml .Values.register.register.resources | nindent 12 }} + volumeMounts: + - name: register-configmap + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + volumes: + - name: register-configmap + configMap: + name: register-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongo-register + labels: + io.kompose.service: mongo-register + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.mongoRegister.replicas }} + selector: + matchLabels: + io.kompose.service: mongo-register + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: mongo-register + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: MONGO_INITDB_ROOT_PASSWORD + value: {{ quote .Values.mongoRegister.mongo.env.mongoInitdbRootPassword }} + - name: MONGO_INITDB_ROOT_USERNAME + value: {{ quote .Values.mongoRegister.mongo.env.mongoInitdbRootUsername }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.mongoRegister.mongo.image.repository }}:{{ .Values.mongoRegister.mongo.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.mongoRegister.mongo.image.imagePullPolicy }} + name: mongo-register + ports: + - containerPort: 27017 + resources: + {{- toYaml .Values.mongoRegister.mongo.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 27017 +# initialDelaySeconds: 5 + periodSeconds: 5 + restartPolicy: Always +{{- end }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: logs + labels: + io.kompose.service: logs + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.logs.replicas }} + selector: + matchLabels: + io.kompose.service: logs + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: logs + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-logs-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: MONITORING + value: {{ quote .Values.logs.logs.env.monitoring }} + image: {{ .Values.logs.logs.image.repository }}:{{ .Values.logs.logs.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.logs.logs.image.imagePullPolicy }} + name: logs + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-logs-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.logs.logs.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: capif-logs-config + configMap: + name: capif-logs-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongo + labels: + io.kompose.service: mongo + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.mongo.replicas }} + strategy: + type: Recreate + selector: + matchLabels: + io.kompose.service: mongo + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: mongo + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: MONGO_INITDB_ROOT_PASSWORD + value: {{ quote .Values.mongo.mongo.env.mongoInitdbRootPassword }} + - name: MONGO_INITDB_ROOT_USERNAME + value: {{ quote .Values.mongo.mongo.env.mongoInitdbRootUsername }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.mongo.mongo.image.repository }}:{{ .Values.mongo.mongo.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.mongo.mongo.image.imagePullPolicy }} + name: mongo + ports: + - containerPort: 27017 + securityContext: + runAsUser: 0 + {{- if eq .Values.mongo.persistence.enable "true" }} + volumeMounts: + - name: mongo-pvc + mountPath: /data/db + {{- end }} + resources: + {{- toYaml .Values.mongo.mongo.resources | nindent 12 }} + livenessProbe: + tcpSocket: + port: 27017 + initialDelaySeconds: 20 + periodSeconds: 5 + readinessProbe: + tcpSocket: + port: 27017 +# initialDelaySeconds: 5 + periodSeconds: 5 + - name: mongo-helper + image: busybox + command: + - sh + - -c + - while true ; do echo alive ; sleep 10 ; done + {{- if eq .Values.mongo.persistence.enable "true" }} + volumeMounts: + - mountPath: /mongodata + name: mongo-pvc + {{- end }} + {{- if eq .Values.mongo.persistence.enable "true" }} + volumes: + - name: mongo-pvc + persistentVolumeClaim: + claimName: mongo-pvc + {{- end }} + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongo-express + labels: + io.kompose.service: mongo-express + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.mongoExpress.replicas }} + selector: + matchLabels: + io.kompose.service: mongo-express + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: mongo-express + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: ME_CONFIG_MONGODB_ADMINPASSWORD + value: {{ quote .Values.mongoExpress.mongoExpress.env.meConfigMongodbAdminpassword + }} + - name: ME_CONFIG_MONGODB_ADMINUSERNAME + value: {{ quote .Values.mongoExpress.mongoExpress.env.meConfigMongodbAdminusername + }} + - name: ME_CONFIG_MONGODB_URL + value: {{ quote .Values.mongoExpress.mongoExpress.env.meConfigMongodbUrl }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.mongoExpress.mongoExpress.image.repository }}:{{ .Values.mongoExpress.mongoExpress.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.mongoExpress.mongoExpress.image.imagePullPolicy }} + name: mongo-express + ports: + - containerPort: 8081 + resources: + {{- toYaml .Values.mongoExpress.mongoExpress.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8081 +# initialDelaySeconds: 0 + periodSeconds: 5 + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx + labels: + io.kompose.service: nginx + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.nginx.replicas }} + selector: + matchLabels: + io.kompose.service: nginx + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: nginx + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.nginx.nginx.env.capifHostname }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.parametersVault.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.parametersVault.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.parametersVault.env.vaultAccessToken }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.nginx.nginx.image.repository }}:{{ .Values.nginx.nginx.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.nginx.nginx.image.imagePullPolicy }} + name: nginx + ports: + - containerPort: 8080 + - containerPort: 443 + livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 20 + periodSeconds: 5 +# readinessProbe: +# tcpSocket: +# port: 8080 +# initialDelaySeconds: 60 +# periodSeconds: 5 + resources: + {{- toYaml .Values.nginx.nginx.resources | nindent 12 }} + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: published-apis + labels: + io.kompose.service: published-apis + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.publishedApis.replicas }} + selector: + matchLabels: + io.kompose.service: published-apis + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: published-apis + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-published-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: MONITORING + value: {{ quote .Values.publishedApis.publishedApis.env.monitoring }} + image: {{ .Values.publishedApis.publishedApis.image.repository }}:{{ .Values.publishedApis.publishedApis.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.publishedApis.publishedApis.image.imagePullPolicy }} + name: published-apis + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-published-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.publishedApis.publishedApis.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: capif-published-config + configMap: + name: capif-published-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis + labels: + io.kompose.service: redis + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.redis.replicas }} + selector: + matchLabels: + io.kompose.service: redis + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: redis + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - args: + - redis-server + env: + - name: REDIS_REPLICATION_MODE + value: {{ quote .Values.redis.redis.env.redisReplicationMode }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + image: {{ .Values.redis.redis.image.repository }}:{{ .Values.redis.redis.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.redis.redis.image.imagePullPolicy }} + name: redis + ports: + - containerPort: 6379 + resources: + {{- toYaml .Values.redis.redis.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 6379 +# initialDelaySeconds: 5 + periodSeconds: 5 + livenessProbe: + tcpSocket: + port: 6379 + initialDelaySeconds: 5 + periodSeconds: 5 + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: service-apis + labels: + io.kompose.service: service-apis + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert +spec: + replicas: {{ .Values.serviceApis.replicas }} + selector: + matchLabels: + io.kompose.service: service-apis + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + io.kompose.network/services-default: "true" + io.kompose.service: service-apis + {{- include "capif.selectorLabels" . | nindent 8 }} + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/capif-service-configmap.yaml") . | sha256sum }} + spec: + hostAliases: + - ip: "{{ .Values.ingress.ip }}" + hostnames: + - "{{ .Values.nginx.nginx.env.capifHostname }}" + containers: + - env: + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + - name: MONITORING + value: {{ quote .Values.serviceApis.serviceApis.env.monitoring }} + image: {{ .Values.serviceApis.serviceApis.image.repository }}:{{ .Values.serviceApis.serviceApis.image.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.serviceApis.serviceApis.image.imagePullPolicy }} + name: service-apis + ports: + - containerPort: 8080 + volumeMounts: + - name: capif-service-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + resources: + {{- toYaml .Values.serviceApis.serviceApis.resources | nindent 12 }} + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: capif-service-config + configMap: + name: capif-service-configmap + items: + - key: "config.yaml" + path: "config.yaml" + restartPolicy: Always \ No newline at end of file diff --git a/helm/capif/templates/fluent-bit-service.yaml b/helm/capif/templates/fluent-bit-service.yaml new file mode 100644 index 0000000..90653b3 --- /dev/null +++ b/helm/capif/templates/fluent-bit-service.yaml @@ -0,0 +1,24 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + creationTimestamp: null + labels: + io.kompose.service: fluent-bit + {{- include "capif.labels" . | nindent 4 }} + name: fluent-bit +spec: + ports: + - name: "24224-tcp" + port: 24224 + targetPort: 24224 + - name: 24224-udp + port: 24224 + protocol: UDP + targetPort: 24224 + selector: + io.kompose.service: fluent-bit +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/fluentbit-configmap.yaml b/helm/capif/templates/fluentbit-configmap.yaml new file mode 100644 index 0000000..20467b1 --- /dev/null +++ b/helm/capif/templates/fluentbit-configmap.yaml @@ -0,0 +1,24 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: fluent-bit-configmap +data: + LOKI_URL: {{ quote .Values.monitoring.fluentBit.env.lokiUrl }} + fluent-bit.conf: | + [INPUT] + Name forward + Listen 0.0.0.0 + Port 24224 + [Output] + Name grafana-loki + Match * + Url ${LOKI_URL} + RemoveKeys source + Labels {job="fluent-bit"} + LabelKeys container_name, traceID + BatchWait 1s + BatchSize 1001024 + LineFormat json + LogLevel info +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/fluentbit-deployment.yaml b/helm/capif/templates/fluentbit-deployment.yaml new file mode 100644 index 0000000..925ec02 --- /dev/null +++ b/helm/capif/templates/fluentbit-deployment.yaml @@ -0,0 +1,59 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: fluent-bit + {{- include "capif.labels" . | nindent 4 }} + name: fluent-bit +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: fluent-bit + {{- include "capif.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + checksum/config: {{ include (print $.Template.BasePath "/fluentbit-configmap.yaml") . | sha256sum }} + creationTimestamp: null + labels: + io.kompose.network/monitoring-default: "true" + io.kompose.service: fluent-bit + {{- include "capif.selectorLabels" . | nindent 8 }} + spec: + containers: + - env: + - name: LOKI_URL + valueFrom: + configMapKeyRef: + name: fluent-bit-configmap + key: LOKI_URL + image: {{ .Values.monitoring.fluentBit.image.repository }}:{{ .Values.monitoring.fluentBit.image.tag }} + name: fluent-bit + ports: + - containerPort: 24224 + - containerPort: 24224 + protocol: UDP + resources: + {{- toYaml .Values.monitoring.fluentBit.resources | nindent 12 }} + volumeMounts: + - name: fluent-bit-conf + mountPath: /fluent-bit/etc/fluent-bit.conf + subPath: fluent-bit.conf + restartPolicy: Always + volumes: + - name: fluent-bit-conf + configMap: + name: fluent-bit-configmap + items: + - key: "fluent-bit.conf" + path: "fluent-bit.conf" +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-configmap.yaml b/helm/capif/templates/grafana-configmap.yaml new file mode 100644 index 0000000..654101f --- /dev/null +++ b/helm/capif/templates/grafana-configmap.yaml @@ -0,0 +1,108 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: datasources +data: + datasources.yaml: | + apiVersion: 1 + datasources: + - name: Loki + type: loki + uid: e4f43364-7019-45a7-aa7a-14ce2d4ddb0b + typeName: Loki + typeLogoUrl: public/app/plugins/datasource/loki/img/loki_icon.svg + access: proxy + url: {{ .Values.monitoring.grafana.env.lokiUrl }} + user: '' + database: '' + basicAuth: false + isDefault: false + jsonData: + derivedFields: + - datasourceUid: fee7e008-f836-424a-b701-88cad583c715 + matcherRegex: '"traceID":\s*"([a-fA-F0-9]+)"' + name: traceID + url: "$${__value.raw}" + readOnly: false + - name: Prometheus + type: prometheus + typeName: Prometheus + typeLogoUrl: public/app/plugins/datasource/prometheus/img/prometheus_logo.svg + access: proxy + url: {{ .Values.monitoring.grafana.env.prometheusUrl }} + uid: af6b44aa-0703-4979-825c-c1afba946534 + user: '' + database: '' + basicAuth: false + isDefault: false + jsonData: + httpMethod: POST + prometheusType: Prometheus + prometheusVersion: 2.40.1 + readOnly: false + - name: Tempo + type: tempo + typeName: Tempo + typeLogoUrl: public/app/plugins/datasource/tempo/img/tempo_logo.svg + uid: fee7e008-f836-424a-b701-88cad583c715 + access: proxy + url: {{ .Values.monitoring.grafana.env.tempoUrl }} + user: '' + database: '' + basicAuth: false + isDefault: false + jsonData: + lokiSearch: + datasourceUid: e4f43364-7019-45a7-aa7a-14ce2d4ddb0b + readOnly: false +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: default +data: + default.yaml: | + apiVersion: 1 + providers: + - name: Default # A uniquely identifiable name for the provider + orgId: 1 + folder: "" # The folder where to place the dashboards + folderUid: "" + type: file + disableDeletion: false + allowUiUpdates: true + options: + path: /var/lib/grafana/dashboards + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: docker-monitoring +data: + Docker-monitoring.json: |- +{{ .Files.Get "docker-monitoring.json" | indent 4 }} + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: kubernetes-dashboard +data: + kubernetes-dashboard.json: | +{{ .Files.Get "kubernetes-dashboard.json" | indent 4 }} + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: loki-logs +data: + loki-logs.json: | +{{ .Files.Get "loki-logs.json" | indent 4 }} +{{- end }} diff --git a/helm/capif/templates/grafana-deployment.yaml b/helm/capif/templates/grafana-deployment.yaml new file mode 100644 index 0000000..844f32e --- /dev/null +++ b/helm/capif/templates/grafana-deployment.yaml @@ -0,0 +1,109 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: grafana + {{- include "capif.labels" . | nindent 4 }} + name: grafana +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + io.kompose.service: grafana + {{- include "capif.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + checksum/config: {{ include (print $.Template.BasePath "/grafana-configmap.yaml") . | sha256sum }} + labels: + io.kompose.network/monitoring-default: "true" + io.kompose.service: grafana + {{- include "capif.selectorLabels" . | nindent 8 }} + spec: + containers: + - env: + - name: GF_AUTH_ANONYMOUS_ENABLED + value: {{ quote .Values.monitoring.grafana.env.gfAuthAnonymousEnable }} + - name: GF_SECURITY_ALLOW_EMBEDDING + value: {{ quote .Values.monitoring.grafana.env.gfSecurityAllowEmbedding }} + - name: GF_PATHS_PROVISIONING + value: /etc/grafana/provisioning + image: {{ .Values.monitoring.grafana.image.repository }}:{{ .Values.monitoring.grafana.image.tag }} + name: grafana + envFrom: + - secretRef: + name: grafana-secrets + ports: + - containerPort: 3000 + resources: + {{- toYaml .Values.monitoring.grafana.resources | nindent 12 }} + securityContext: + runAsUser: 0 + volumeMounts: + - name: grafana-datasources + mountPath: /etc/grafana/provisioning/datasources/datasources.yaml + subPath: datasources.yaml + - name: grafana-default + mountPath: /etc/grafana/provisioning/dashboards/default.yaml + subPath: default.yaml + - name: grafana-docker + mountPath: /var/lib/grafana/dashboards/Docker-monitoring.json + subPath: Docker-monitoring.json + - name: kubernetes-dashboard + mountPath: /var/lib/grafana/dashboards/kubernetes-dashboard.json + subPath: kubernetes-dashboard.json + - name: grafana-loki + mountPath: /var/lib/grafana/dashboards/Loki-Logs.json + subPath: loki-logs.json + {{- if eq .Values.monitoring.grafana.persistence.enable "true" }} + - name: grafana-claim0 + mountPath: /var/lib/grafana + {{- end }} + volumes: + - name: grafana-datasources + configMap: + name: datasources + items: + - key: "datasources.yaml" + path: "datasources.yaml" + - name: grafana-default + configMap: + name: default + items: + - key: "default.yaml" + path: "default.yaml" + - name: grafana-docker + configMap: + name: docker-monitoring + items: + - key: "Docker-monitoring.json" + path: "Docker-monitoring.json" + - name: kubernetes-dashboard + configMap: + name: kubernetes-dashboard + items: + - key: "kubernetes-dashboard.json" + path: "kubernetes-dashboard.json" + - name: grafana-loki + configMap: + name: loki-logs + items: + - key: "loki-logs.json" + path: "loki-logs.json" + {{- if eq .Values.monitoring.grafana.persistence.enable "true" }} + - name: grafana-claim0 + persistentVolumeClaim: + claimName: grafana-claim0 + {{- end }} + restartPolicy: Always +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-ingress-route.yaml b/helm/capif/templates/grafana-ingress-route.yaml new file mode 100644 index 0000000..2e2648b --- /dev/null +++ b/helm/capif/templates/grafana-ingress-route.yaml @@ -0,0 +1,18 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.grafana.ingressRoute.enable "true" }} +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: grafana-ingress-route +spec: + entryPoints: [web] + routes: + - kind: Rule + match: Host(`{{ .Values.monitoring.grafana.ingressRoute.host }}`) + services: + - kind: Service + name: grafana + port: {{ .Values.monitoring.grafana.service.port }} + scheme: http +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-ingress.yaml b/helm/capif/templates/grafana-ingress.yaml new file mode 100644 index 0000000..7d7d0cb --- /dev/null +++ b/helm/capif/templates/grafana-ingress.yaml @@ -0,0 +1,34 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if .Values.monitoring.grafana.ingress.enabled -}} +{{- $svcPort := .Values.monitoring.grafana.service.port -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: grafana-ingress + labels: + {{- include "capif.labels" . | nindent 4 }} + {{- with .Values.monitoring.grafana.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.monitoring.grafana.ingress.ingressClassName }} + ingressClassName: {{ .Values.monitoring.grafana.ingress.ingressClassName }} +{{- end }} + rules: + {{- range .Values.monitoring.grafana.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: grafana + port: + number: {{ $svcPort }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/grafana-pvc.yaml b/helm/capif/templates/grafana-pvc.yaml new file mode 100644 index 0000000..b2c6672 --- /dev/null +++ b/helm/capif/templates/grafana-pvc.yaml @@ -0,0 +1,16 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.grafana.persistence.enable "true" }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + io.kompose.service: grafana-claim0 + name: grafana-claim0 +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.monitoring.grafana.persistence.storage }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-secrets.yaml b/helm/capif/templates/grafana-secrets.yaml new file mode 100644 index 0000000..a6796d4 --- /dev/null +++ b/helm/capif/templates/grafana-secrets.yaml @@ -0,0 +1,10 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: Secret +metadata: + name: grafana-secrets +type: Opaque +data: + GF_AUTH_ANONYMOUS_ORG_ROLE: {{ .Values.monitoring.grafana.env.gfAuthAnonymousOrgRole | b64enc | quote }} + GF_SECURITY_ADMIN_PASSWORD: {{ .Values.monitoring.grafana.env.gfSecurityAdminPassword | b64enc | quote }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-service.yaml b/helm/capif/templates/grafana-service.yaml new file mode 100644 index 0000000..c628043 --- /dev/null +++ b/helm/capif/templates/grafana-service.yaml @@ -0,0 +1,17 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: Service +metadata: + name: grafana + labels: + {{- include "capif.labels" . | nindent 4 }} +spec: + type: {{ .Values.monitoring.grafana.service.type }} + ports: + - port: {{ .Values.monitoring.grafana.service.port }} + targetPort: {{ .Values.monitoring.grafana.service.port }} + protocol: TCP + name: http-port + selector: + io.kompose.service: grafana +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/logs.yaml b/helm/capif/templates/logs.yaml new file mode 100644 index 0000000..7382eff --- /dev/null +++ b/helm/capif/templates/logs.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: logs + labels: + io.kompose.service: logs + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.logs.type }} + selector: + io.kompose.service: logs + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.logs.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/loki-deployment.yaml b/helm/capif/templates/loki-deployment.yaml new file mode 100644 index 0000000..cadf37d --- /dev/null +++ b/helm/capif/templates/loki-deployment.yaml @@ -0,0 +1,54 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: loki + {{- include "capif.labels" . | nindent 4 }} + name: loki +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + io.kompose.service: loki + {{- include "capif.selectorLabels" . | nindent 6 }} + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.network/monitoring-default: "true" + io.kompose.service: loki + {{- include "capif.selectorLabels" . | nindent 8 }} + spec: + containers: + - args: + - -config.file=/etc/loki/local-config.yaml + image: {{ .Values.monitoring.loki.image.repository }}:{{ .Values.monitoring.loki.image.tag }} + name: loki + ports: + - containerPort: 3100 + {{- if eq .Values.monitoring.loki.persistence.enable "true" }} + volumeMounts: + - name: loki-claim0 + mountPath: /loki/wal + {{- end }} + resources: + {{- toYaml .Values.monitoring.loki.resources | nindent 12 }} + securityContext: + runAsUser: 0 + {{- if eq .Values.monitoring.loki.persistence.enable "true" }} + volumes: + - name: loki-claim0 + persistentVolumeClaim: + claimName: loki-claim0 + {{- end }} + restartPolicy: Always +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/loki-pvc.yaml b/helm/capif/templates/loki-pvc.yaml new file mode 100644 index 0000000..7da7816 --- /dev/null +++ b/helm/capif/templates/loki-pvc.yaml @@ -0,0 +1,16 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.loki.persistence.enable "true" }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + io.kompose.service: loki-claim0 + name: loki-claim0 +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.monitoring.loki.persistence.storage }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/loki-service.yaml b/helm/capif/templates/loki-service.yaml new file mode 100644 index 0000000..cf711a9 --- /dev/null +++ b/helm/capif/templates/loki-service.yaml @@ -0,0 +1,19 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: loki + {{- include "capif.labels" . | nindent 4 }} + name: loki +spec: + ports: + - name: "loki-port" + port: 3100 + targetPort: 3100 + selector: + io.kompose.service: loki +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/mongo-express.yaml b/helm/capif/templates/mongo-express.yaml new file mode 100644 index 0000000..28d553b --- /dev/null +++ b/helm/capif/templates/mongo-express.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongo-express + labels: + io.kompose.service: mongo-express + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.mongoExpress.type }} + selector: + io.kompose.service: mongo-express + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.mongoExpress.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/mongo-pvc.yaml b/helm/capif/templates/mongo-pvc.yaml new file mode 100644 index 0000000..2996d57 --- /dev/null +++ b/helm/capif/templates/mongo-pvc.yaml @@ -0,0 +1,16 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.mongo.persistence.enable "true" }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + io.kompose.service: mongo-pvc + name: mongo-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.mongo.persistence.storage }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/mongo-register.yaml b/helm/capif/templates/mongo-register.yaml new file mode 100644 index 0000000..82b307f --- /dev/null +++ b/helm/capif/templates/mongo-register.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongo-register + labels: + io.kompose.service: mongo-register + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.mongoRegister.type }} + selector: + io.kompose.service: mongo-register + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.mongoRegister.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/mongo.yaml b/helm/capif/templates/mongo.yaml new file mode 100644 index 0000000..8642764 --- /dev/null +++ b/helm/capif/templates/mongo.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongo + labels: + io.kompose.service: mongo + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.mongo.type }} + selector: + io.kompose.service: mongo + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.mongo.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ingress-route.yaml b/helm/capif/templates/nginx-ingress-route.yaml new file mode 100644 index 0000000..57ca0be --- /dev/null +++ b/helm/capif/templates/nginx-ingress-route.yaml @@ -0,0 +1,17 @@ +{{- if eq .Values.nginx.ingressType "IngressRoute" }} +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: nginx-capif-ingress-route +spec: + entryPoints: [web] + routes: + - kind: Rule + match: Host(`{{ .Values.nginx.nginx.env.capifHostname }} && Path(`/ca-root`, `/sign-csr`, `/certdata`, `/register`, `/testdata`, `/getauth`, `/test`)`) + services: + - kind: Service + name: nginx + port: 8080 + scheme: http +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ssl-ingress-route.yaml b/helm/capif/templates/nginx-ssl-ingress-route.yaml new file mode 100644 index 0000000..8c806b6 --- /dev/null +++ b/helm/capif/templates/nginx-ssl-ingress-route.yaml @@ -0,0 +1,18 @@ +{{- if eq .Values.nginx.ingressType "IngressRoute" }} +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: nginx-ssl-capif-ingress-route +spec: + entryPoints: [web] + routes: + - kind: Rule + match: Host(`{{ .Values.nginx.nginx.env.capifHostname }}`) + services: + - kind: Service + name: nginx + port: 443 + tls: + passthrough: true +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ssl-route.yaml b/helm/capif/templates/nginx-ssl-route.yaml new file mode 100644 index 0000000..3e24b72 --- /dev/null +++ b/helm/capif/templates/nginx-ssl-route.yaml @@ -0,0 +1,22 @@ +{{- if eq .Values.env "openshift" }} +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + labels: + name: nginx-ssl +spec: + host: {{ .Values.nginx.nginx.env.capifHostname }} + port: + targetPort: "443" + tls: + termination: passthrough + to: + kind: Service + name: nginx + weight: 100 +status: + ingress: + - conditions: + host: {{ .Values.nginx.nginx.env.capifHostname }} + routerCanonicalHostname: router-default.apps.ocp-epg.hi.inet +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ssl.yaml b/helm/capif/templates/nginx-ssl.yaml new file mode 100644 index 0000000..275e2c7 --- /dev/null +++ b/helm/capif/templates/nginx-ssl.yaml @@ -0,0 +1,32 @@ +{{- if eq .Values.nginx.ingressType "Ingress" }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: nginx-register + labels: + {{- include "capif.labels" . | nindent 4 }} + {{- with .Values.nginx.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + cert-manager.io/issuer: letsencrypt-issuer + {{- end }} +spec: +{{- if .Values.nginx.ingressClassName }} + ingressClassName: {{ .Values.nginx.ingressClassName }} +{{- end }} + rules: + - host: "register{{ .Values.nginx.nginx.env.capifHostname }}" + http: + paths: + - backend: + service: + name: 'register' + port: + number: 8084 + path: / + pathType: Prefix + tls: + - hosts: + - "register{{ .Values.nginx.nginx.env.capifHostname }}" + secretName: letsencrypt-secret +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx.yaml b/helm/capif/templates/nginx.yaml new file mode 100644 index 0000000..61856f5 --- /dev/null +++ b/helm/capif/templates/nginx.yaml @@ -0,0 +1,48 @@ +{{- if eq .Values.nginx.ingressType "Ingress" }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: nginx + labels: + {{- include "capif.labels" . | nindent 4 }} + {{- with .Values.nginx.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" + {{- end }} +spec: +{{- if .Values.nginx.ingressClassName }} + ingressClassName: {{ .Values.nginx.ingressClassName }} +{{- end }} + rules: + - host: "{{ .Values.nginx.nginx.env.capifHostname }}" + http: + paths: + - backend: + service: + name: 'nginx' + port: + number: 443 + path: / + pathType: Prefix +{{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx + labels: + io.kompose.service: nginx + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.nginx.type }} + selector: + io.kompose.service: nginx + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.nginx.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/otel-collector-configmap.yaml b/helm/capif/templates/otel-collector-configmap.yaml new file mode 100644 index 0000000..fed1535 --- /dev/null +++ b/helm/capif/templates/otel-collector-configmap.yaml @@ -0,0 +1,37 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: open-telemetry-configmap +data: + otel-collector-config.yaml: | + receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:55680 + http: + endpoint: 0.0.0.0:4318 + + processors: + batch: + + + exporters: + logging: + loglevel: debug + otlp: + #timeout: 60s + endpoint: {{ .Values.monitoring.otel.configMap.tempoEndpoint }} + tls: + insecure: true + + + service: + pipelines: + traces: + receivers: [otlp] + processors: [batch] + # exporters: [otlp] + exporters: [otlp] +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/otel-collector-deployment.yaml b/helm/capif/templates/otel-collector-deployment.yaml new file mode 100644 index 0000000..8c83eca --- /dev/null +++ b/helm/capif/templates/otel-collector-deployment.yaml @@ -0,0 +1,54 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: otel-collector + {{- include "capif.labels" . | nindent 4 }} + name: otel-collector +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: otel-collector + {{- include "capif.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + checksum/config: {{ include (print $.Template.BasePath "/otel-collector-configmap.yaml") . | sha256sum }} + labels: + io.kompose.network/monitoring-default: "true" + io.kompose.service: otel-collector + {{- include "capif.selectorLabels" . | nindent 8 }} + spec: + containers: + - args: + - --config + - /etc/otel-collector-config.yaml + image: {{ .Values.monitoring.otel.image.repository }}:{{ .Values.monitoring.otel.image.tag }} + name: otel-collector + ports: + - containerPort: 55680 + - containerPort: 4317 + resources: + {{- toYaml .Values.monitoring.otel.resources | nindent 12 }} + volumeMounts: + - name: op-telemetry + mountPath: /etc/otel-collector-config.yaml + subPath: otel-collector-config.yaml + restartPolicy: Always + volumes: + - name: op-telemetry + configMap: + name: open-telemetry-configmap + items: + - key: "otel-collector-config.yaml" + path: "otel-collector-config.yaml" +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/otel-collector-service.yaml b/helm/capif/templates/otel-collector-service.yaml new file mode 100644 index 0000000..761b8ce --- /dev/null +++ b/helm/capif/templates/otel-collector-service.yaml @@ -0,0 +1,22 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: otel-collector + {{- include "capif.labels" . | nindent 4 }} + name: otel-collector +spec: + ports: + - name: "grpc-port" + port: 55680 + targetPort: 55680 + - name: "http-port" + port: 4318 + targetPort: 4318 + selector: + io.kompose.service: otel-collector +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-clusterrole.yaml b/helm/capif/templates/prometheus-clusterrole.yaml new file mode 100644 index 0000000..3470ffd --- /dev/null +++ b/helm/capif/templates/prometheus-clusterrole.yaml @@ -0,0 +1,49 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.prometheus.enable "true" }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: prometheus + labels: + app: prometheus +rules: +- apiGroups: [""] + resources: + - nodes + - nodes/proxy + - services + - endpoints + - pods + verbs: ["get", "list", "watch"] +- apiGroups: + - extensions + resources: + - ingresses + verbs: ["get", "list", "watch"] +- nonResourceURLs: ["/metrics"] + verbs: ["get"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: prometheus + namespace: {{ .Release.Namespace }} + labels: + app: prometheus +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: prometheus + labels: + app: prometheus +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prometheus +subjects: +- kind: ServiceAccount + name: prometheus + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-configmap.yaml b/helm/capif/templates/prometheus-configmap.yaml new file mode 100644 index 0000000..d2ab952 --- /dev/null +++ b/helm/capif/templates/prometheus-configmap.yaml @@ -0,0 +1,141 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.prometheus.enable "true" }} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app: prometheus + name: prometheus-config +data: + prometheus.rules: |- + groups: + - name: devopscube alert + rules: + - alert: High Pod Memory + expr: sum(container_memory_usage_bytes) > 1 + for: 1m + labels: + severity: slack + annotations: + summary: High Memory Usage + prometheus.yml: |- + global: + scrape_interval: 30s + scrape_timeout: 10s + scrape_configs: + #------------- configuration to collect pods metrics kubelet ------------------- + - job_name: 'kubernetes-cadvisor' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor + #------------- configuration to collect pods metrics ------------------- + - job_name: 'kubernetes-pods' + honor_labels: true + kubernetes_sd_configs: + - role: pod + relabel_configs: + # select only those pods that has "prometheus.io/scrape: true" annotation + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + # set metrics_path (default is /metrics) to the metrics path specified in "prometheus.io/path: " annotation. + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + # set the scrapping port to the port specified in "prometheus.io/port: " annotation and set address accordingly. + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: kubernetes_pod_name + + #-------------- configuration to collect metrics from service endpoints ----------------------- + - job_name: 'kubernetes-service-endpoints' + honor_labels: true + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + # select only those endpoints whose service has "prometheus.io/scrape: true" annotation + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + # set the metrics_path to the path specified in "prometheus.io/path: " annotation. + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + # set the scrapping port to the port specified in "prometheus.io/port: " annotation and set address accordingly. + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_name + + #---------------- configuration to collect metrics from kubernetes apiserver ------------------------- + - job_name: 'kubernetes-apiservers' + honor_labels: true + kubernetes_sd_configs: + - role: endpoints + # kubernetes apiserver serve metrics on a TLS secure endpoints. so, we have to use "https" scheme + scheme: https + # we have to provide certificate to establish tls secure connection + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # bearer_token_file is required for authorizating prometheus server to kubernetes apiserver + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: default;kubernetes;https + + #--------------- configuration to collect metrics from nodes ----------------------- + - job_name: 'kubernetes-nodes' + honor_labels: true + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-deployment.yaml b/helm/capif/templates/prometheus-deployment.yaml new file mode 100644 index 0000000..d70cf09 --- /dev/null +++ b/helm/capif/templates/prometheus-deployment.yaml @@ -0,0 +1,68 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.prometheus.enable "true" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prometheus + labels: + app: prometheus + {{- include "capif.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: prometheus + {{- include "capif.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/prometheus-configmap.yaml") . | sha256sum }} + labels: + app: prometheus + {{- include "capif.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: prometheus + containers: + - name: prometheus + image: {{ .Values.monitoring.prometheus.image.repository }}:{{ .Values.monitoring.prometheus.image.tag }} + args: + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus/" + - "--storage.tsdb.retention.time={{.Values.monitoring.prometheus.retentionTime }}" + ports: + - containerPort: 9090 + resources: + {{- toYaml .Values.monitoring.prometheus.resources | nindent 12 }} + securityContext: + runAsUser: 0 + livenessProbe: + tcpSocket: + port: 9090 + initialDelaySeconds: 20 + volumeMounts: + - name: prometheus-config + mountPath: /etc/prometheus/ + {{- if eq .Values.monitoring.prometheus.persistence.enable "true" }} + - name: prometheus-storage-volume + mountPath: /prometheus/ + {{ else }} + - name: prometheus-storage + mountPath: /prometheus/ + {{- end }} + volumes: + - name: prometheus-config + configMap: + defaultMode: 420 + name: prometheus-config + {{- if eq .Values.monitoring.prometheus.persistence.enable "true" }} + - name: prometheus-storage-volume + persistentVolumeClaim: + claimName: prometheus-pvc + {{ else }} + - name: prometheus-storage + emptyDir: {} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-ingress-route.yaml b/helm/capif/templates/prometheus-ingress-route.yaml new file mode 100644 index 0000000..b7a0d2b --- /dev/null +++ b/helm/capif/templates/prometheus-ingress-route.yaml @@ -0,0 +1,20 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.prometheus.enable "true" }} +{{- if eq .Values.monitoring.prometheus.ingressRoute.enable "true" }} +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: prometheus-ingress-route +spec: + entryPoints: [web] + routes: + - kind: Rule + match: Host(`{{ .Values.monitoring.prometheus.ingressRoute.host }}`) + services: + - kind: Service + name: prometheus + port: {{ .Values.monitoring.prometheus.service.port }} + scheme: http +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-ingress.yaml b/helm/capif/templates/prometheus-ingress.yaml new file mode 100644 index 0000000..d082973 --- /dev/null +++ b/helm/capif/templates/prometheus-ingress.yaml @@ -0,0 +1,36 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.prometheus.enable "true" }} +{{- if .Values.monitoring.prometheus.ingress.enabled -}} +{{- $svcPort := .Values.monitoring.prometheus.service.port -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: prometheus-ingress + labels: + {{- include "capif.labels" . | nindent 4 }} + {{- with .Values.monitoring.prometheus.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.monitoring.prometheus.ingress.ingressClassName }} + ingressClassName: {{ .Values.monitoring.prometheus.ingress.ingressClassName }} +{{- end }} + rules: + {{- range .Values.monitoring.prometheus.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: prometheus + port: + number: {{ $svcPort }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/prometheus-pvc.yaml b/helm/capif/templates/prometheus-pvc.yaml new file mode 100644 index 0000000..0ba676f --- /dev/null +++ b/helm/capif/templates/prometheus-pvc.yaml @@ -0,0 +1,19 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.prometheus.enable "true" }} +{{- if eq .Values.monitoring.prometheus.persistence.enable "true" }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: prometheus-pvc + labels: + app: prometheus + {{- include "capif.labels" . | nindent 4 }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.monitoring.prometheus.persistence.storage }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-service.yaml b/helm/capif/templates/prometheus-service.yaml new file mode 100644 index 0000000..778dbd5 --- /dev/null +++ b/helm/capif/templates/prometheus-service.yaml @@ -0,0 +1,22 @@ +{{- if eq .Values.monitoring.enable "true" }} +{{- if eq .Values.monitoring.prometheus.enable "true" }} +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/path: /metrics + prometheus.io/port: {{ quote .Values.monitoring.prometheus.service.port }} + prometheus.io/scrape: "true" + name: prometheus + labels: + {{- include "capif.labels" . | nindent 4 }} +spec: + type: {{ .Values.monitoring.prometheus.service.type }} + ports: + - port: {{ .Values.monitoring.prometheus.service.port }} + protocol: TCP + targetPort: {{ .Values.monitoring.prometheus.service.port }} + selector: + app: prometheus +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/published-apis.yaml b/helm/capif/templates/published-apis.yaml new file mode 100644 index 0000000..a5444f1 --- /dev/null +++ b/helm/capif/templates/published-apis.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: published-apis + labels: + io.kompose.service: published-apis + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.publishedApis.type }} + selector: + io.kompose.service: published-apis + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.publishedApis.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/redis.yaml b/helm/capif/templates/redis.yaml new file mode 100644 index 0000000..3254a95 --- /dev/null +++ b/helm/capif/templates/redis.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis + labels: + io.kompose.service: redis + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.redis.type }} + selector: + io.kompose.service: redis + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.redis.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/register-configmap.yaml b/helm/capif/templates/register-configmap.yaml new file mode 100644 index 0000000..51293a5 --- /dev/null +++ b/helm/capif/templates/register-configmap.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: register-configmap + labels: + {{- include "capif.labels" . | nindent 4 }} +data: + config.yaml: |- + mongo: { + 'user': 'root', + 'password': 'example', + 'db': 'capif_users', + 'col': 'user', + 'host': '{{ .Values.register.register.env.mongoHost }}', + 'port': '{{ .Values.register.register.env.mongoPort }}' + } + ca_factory: { + "url": "{{ .Values.parametersVault.env.vaultHostname }}", + "port": "{{ .Values.parametersVault.env.vaultPort }}", + "token": "{{ .Values.parametersVault.env.vaultAccessToken }}" + } \ No newline at end of file diff --git a/helm/capif/templates/register.yaml b/helm/capif/templates/register.yaml new file mode 100644 index 0000000..2de1d64 --- /dev/null +++ b/helm/capif/templates/register.yaml @@ -0,0 +1,19 @@ +{{- if eq .Values.register.enable "true" }} +apiVersion: v1 +kind: Service +metadata: + name: register + labels: + io.kompose.service: register + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.register.type }} + selector: + io.kompose.service: register + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.register.ports | toYaml | nindent 2 -}} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/renderer-configmap.yaml b/helm/capif/templates/renderer-configmap.yaml new file mode 100644 index 0000000..0159fcb --- /dev/null +++ b/helm/capif/templates/renderer-configmap.yaml @@ -0,0 +1,8 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: renderer-configmap +data: + ENABLE_METRICS: {{ quote .Values.monitoring.renderer.env.enableMetrics }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/renderer-deployment.yaml b/helm/capif/templates/renderer-deployment.yaml new file mode 100644 index 0000000..83a7ee2 --- /dev/null +++ b/helm/capif/templates/renderer-deployment.yaml @@ -0,0 +1,44 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: renderer + {{- include "capif.labels" . | nindent 4 }} + name: renderer +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: renderer + {{- include "capif.selectorLabels" . | nindent 6 }} + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + checksum/config: {{ include (print $.Template.BasePath "/renderer-configmap.yaml") . | sha256sum }} + labels: + io.kompose.network/monitoring-default: "true" + io.kompose.service: renderer + {{- include "capif.selectorLabels" . | nindent 8 }} + spec: + containers: + - env: + - name: ENABLE_METRICS + valueFrom: + configMapKeyRef: + name: renderer-configmap + key: ENABLE_METRICS + image: {{ .Values.monitoring.renderer.image.repository }}:{{ .Values.monitoring.renderer.image.tag }} + name: grafana-image-renderer + ports: + - containerPort: 8081 + resources: + {{- toYaml .Values.monitoring.renderer.resources | nindent 12 }} + restartPolicy: Always +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/renderer-service.yaml b/helm/capif/templates/renderer-service.yaml new file mode 100644 index 0000000..471a51d --- /dev/null +++ b/helm/capif/templates/renderer-service.yaml @@ -0,0 +1,18 @@ +{{- if eq .Values.monitoring.enable "true" }} +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose -f docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) + labels: + io.kompose.service: renderer + name: renderer +spec: + ports: + - name: "rendere-port" + port: 8081 + targetPort: 8081 + selector: + io.kompose.service: renderer +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/service-apis.yaml b/helm/capif/templates/service-apis.yaml new file mode 100644 index 0000000..bff1af5 --- /dev/null +++ b/helm/capif/templates/service-apis.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: service-apis + labels: + io.kompose.service: service-apis + {{- include "capif.labels" . | nindent 4 }} + annotations: + kompose.cmd: kompose -f ../services/docker-compose.yml convert + kompose.version: 1.28.0 (c4137012e) +spec: + type: {{ .Values.serviceApis.type }} + selector: + io.kompose.service: service-apis + {{- include "capif.selectorLabels" . | nindent 4 }} + ports: + {{- .Values.serviceApis.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/values.yaml b/helm/capif/values.yaml new file mode 100644 index 0000000..a2aea33 --- /dev/null +++ b/helm/capif/values.yaml @@ -0,0 +1,660 @@ +# -- The Environment variable. Use openshift if you are deploying in Openshift cluster. anotherwise use the field empty +env: "" + +# Use the Ip address dude for the kubernetes to your Ingress Controller ej: kubectl -n NAMESPACE_CAPIF get ing +ingress: + ip: "10.17.173.127" + +monitoring: + enable: "true" + +accessControlPolicy: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/access-control-policy" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP + +CapifClient: + # -- If enable capif client. + enable: "true" + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/client" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP + +apiInvocationLogs: + apiInvocationLogs: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/api-invocation-logs-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP +apiInvokerManagement: + apiInvokerManagement: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/api-invoker-management-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP +apiProviderManagement: + apiProviderManagement: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/api-provider-management-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP +capifEvents: + capifEvents: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/events-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP +capifRoutingInfo: + capifRoutingInfo: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/routing-info-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP +capifSecurity: + capifSecurity: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/security-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP +register: + # -- If register enabled. enable: true, enable: "" = not enabled + enable: "true" + register: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/register" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + env: + mongoHost: mongo-register + mongoPort: 27017 + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8084 + targetPort: 8080 + replicas: 1 + type: ClusterIP +mongoRegister: + mongo: + env: + # User's password MongoDB + mongoInitdbRootPassword: example + # Name of User's mongodb + mongoInitdbRootUsername: root + image: + # -- The docker image repository to use + repository: "mongo" + # -- The docker image tag to use + # @default Chart version + tag: "6.0.2" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + resources: {} +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi + ports: + - name: "27017" + port: 27017 + targetPort: 27017 + replicas: 1 + type: ClusterIP + +kubernetesClusterDomain: cluster.local +logs: + # -- If register enabled. enable: true, enable: "" = not enabled + enable: "true" + logs: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/auditing-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + type: ClusterIP +mongo: + mongo: + env: + # User's password MongoDB + mongoInitdbRootPassword: example + # Name of User's mongodb + mongoInitdbRootUsername: root + image: + # -- The docker image repository to use + repository: "mongo" + # -- The docker image tag to use + # @default Chart version + tag: "6.0.2" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + resources: {} +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi + ports: + - name: "27017" + port: 27017 + targetPort: 27017 + replicas: 1 + type: ClusterIP + # -- If mongo.persistence enabled. enable: true, enable: "" = not enabled + persistence: + enable: "true" + storage: 8Gi +mongoExpress: + mongoExpress: + env: + # User's password MongoDB + meConfigMongodbAdminpassword: example + # Name of User's mongodb + meConfigMongodbAdminusername: root + # URI for connecting MongoDB + meConfigMongodbUrl: mongodb://root:example@mongo:27017/ + image: + # -- The docker image repository to use + repository: "mongo-express" + # -- The docker image tag to use + # @default Chart version + tag: "1.0.0-alpha.4" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8082" + port: 8082 + targetPort: 8081 + replicas: 1 + type: ClusterIP +nginx: + # -- if nginx.ingressType: "Ingress". set up monitoring.prometheus.ingress: true + # and monitoring.grafana.ingress: true + # Use IngressRoute if you want to use Gateway API. ex traefix + ingressType: "Ingress" + ingressClassName: nginx + annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx: + env: + # -- Ingress's host to Capif + capifHostname: "my-capif.apps.ocp-epg.hi.inet" + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/nginx" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + - name: "443" + port: 443 + targetPort: 443 + replicas: 1 + type: ClusterIP +publishedApis: + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + publishedApis: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/publish-service-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + replicas: 1 + type: ClusterIP +redis: + ports: + - name: "6379" + port: 6379 + targetPort: 6379 + redis: + env: + # Mode of replication + redisReplicationMode: master + image: + # -- The docker image repository to use + repository: "redis" + # -- The docker image tag to use + # @default Chart version + tag: "alpine" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + replicas: 1 + type: ClusterIP +serviceApis: + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + replicas: 1 + serviceApis: + image: + # -- The docker image repository to use + repository: "public.ecr.aws/o2v4a8t6/opencapif/discover-service-api" + # -- The docker image tag to use + # @default Chart version + tag: "" + # -- Image pull policy: Always, IfNotPresent + imagePullPolicy: Always + # -- If env.monitoring: true. Setup monitoring.enable: true + env: + monitoring: "true" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + type: ClusterIP +parametersVault: + env: + vaultHostname: vault-internal.mon.svc.cluster.local + vaultPort: 8200 + vaultAccessToken: dev-only-token +# -- With tempo.enabled: false. It won't be deployed +# -- If monitoring.enable: "true". Also enable tempo.enabled: true +tempo: + enabled: true + tempo: + metricsGenerator: + enabled: true + remoteWriteUrl: "http://prometheus.mon.svc.cluster.local:9090/api/v1/write" + persistence: + enabled: true + size: 3Gi +monitoring: + # -- If monitoring enabled. enable: true, enable: "" = not enabled + enable: "true" + fluentBit: + image: + # -- The docker image repository to use + repository: "grafana/fluent-bit-plugin-loki" + # -- The docker image tag to use + # @default Chart version + tag: "latest" + env: + lokiUrl: http://loki:3100/loki/api/v1/push + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + loki: + image: + # -- The docker image repository to use + repository: "grafana/loki" + # -- The docker image tag to use + # @default Chart version + tag: "2.8.0" + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + # -- If grafana.persistence enabled. enable: true, enable: "" = not enabled + persistence: + enable: "true" + storage: 100Mi + otel: + image: + # -- The docker image repository to use + repository: "otel/opentelemetry-collector" + # -- The docker image tag to use + # @default Chart version + tag: "0.81.0" + configMap: + tempoEndpoint: monitoring-capif-tempo:4317 + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + renderer: + image: + # -- The docker image repository to use + repository: "grafana/grafana-image-renderer" + # -- The docker image tag to use + # @default Chart version + tag: "latest" + env: + enableMetrics: "true" + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + prometheus: + # -- With prometheus.enabled: "". It won't be deployed. prometheus.enable: "true" + # -- It will deploy prometheus + enable: "true" + image: + # -- The docker image repository to use + repository: "prom/prometheus" + # -- The docker image tag to use + # @default Chart version + tag: "latest" + retentionTime: 5d + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + persistence: + enable: "true" + storage: 8Gi + service: + type: ClusterIP + port: 9090 + ingress: + enabled: true + ingressClassName: nginx + annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: prometheus.5gnacar.int + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + # -- If ingressRoute enable=true, use monitoring.prometheus.ingress.enabled="" + ingressRoute: + enable: "" + host: prometheus.5gnacar.int + grafana: + image: + # -- The docker image repository to use + repository: "grafana/grafana" + # -- The docker image tag to use + # @default Chart version + tag: "latest" + env: + gfAuthAnonymousEnable: true + gfSecurityAllowEmbedding: true + gfAuthAnonymousOrgRole: Admin + gfSecurityAdminPassword: secure_pass + lokiUrl: http://loki:3100 + prometheusUrl: http://prometheus.mon.svc.cluster.local:9090 + tempoUrl: http://monitoring-capif-tempo:3100 + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + # -- If grafana.persistence enabled. enable: true, enable: "" = not enabled + persistence: + enable: "true" + storage: 100Mi + service: + type: ClusterIP + port: 3000 + # -- If ingress enabled=true, use monitoring.grafana.ingressRoute.enable="" + ingress: + enabled: true + ingressClassName: nginx + annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: grafana.5gnacar.int + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + # -- If ingressRoute enable=true, use monitoring.grafana.ingress.enabled="" + ingressRoute: + enable: "" + host: grafana.5gnacar.int diff --git a/helm/helmfile-capif.yaml b/helm/helmfile-capif.yaml new file mode 100644 index 0000000..610e64a --- /dev/null +++ b/helm/helmfile-capif.yaml @@ -0,0 +1,19 @@ +# helm upgrade --install -n mon monitoring-capif capif/ --set nginx.nginx.env.capifHostname=mon-capif.monitoring.int \ +# --set ingress_ip.oneke="10.17.173.127" --set env=oneke --atomic +helmDefaults: + createNamespace: true + timeout: 600 +releases: + - name: monitoring-capif + chart: ./capif/ + namespace: monitoring +# atomic: true + wait: true + values: + - ./capif/values.yaml + - nginx: + nginx: + env: + capifHostname: monitoring-capif.monitoring.int + - ingress: + ip: "10.17.173.127" \ No newline at end of file diff --git a/helm/vault-job/vault-job.yaml b/helm/vault-job/vault-job.yaml new file mode 100644 index 0000000..6e0e9ce --- /dev/null +++ b/helm/vault-job/vault-job.yaml @@ -0,0 +1,251 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: vault-prepare-certs + namespace: mon + labels: + io.kompose.service: api-invocation-logs + app: capif + app.kubernetes.io/name: capif + app.kubernetes.io/instance: capif +data: + vault-prepare-certs.sh: |- + #!/bin/sh + + echo "install dependencies" + apk add --no-cache jq openssl + + # Establecer las variables de entorno de Vault + + export VAULT_ADDR='http://vault-internal:8200' + + # In standalone's mode. Please use the root's token + # or the token with the sufficient permissions + # to execute the next commands in vault + # otherwise, if use the vault as dev's mode. Just + # type the token's dev. + export VAULT_TOKEN="dev-only-token" + export DOMAIN1=capif.mobilesandbox.cloud + + vault secrets enable pki + + echo "# Generar una CA en Vault #" + vault secrets tune -max-lease-ttl=87600h pki + + vault write -field=certificate pki/root/generate/internal \ + common_name="capif" \ + issuer_name="root-2023" \ + ttl=87600h > root_2023_ca.crt + + echo "# check root_2023_ca.crt #" + cat root_2023_ca.crt + + vault write pki/config/urls \ + issuing_certificates="$VAULT_ADDR/v1/pki/ca" \ + crl_distribution_points="$VAULT_ADDR/v1/pki/crl" + + # # Generar una CA intermedia en Vault + vault secrets enable -path=pki_int pki + + vault secrets tune -max-lease-ttl=43800h pki_int + + vault write -format=json pki_int/intermediate/generate/internal \ + common_name="capif Intermediate Authority" \ + issuer_name="capif-intermediate" \ + | jq -r '.data.csr' > pki_intermediate.csr + + echo "### content pki_intermediate.csr ###" + cat pki_intermediate.csr + + # Firmar la CA intermedia con la CA raíz + vault write -format=json pki/root/sign-intermediate \ + issuer_ref="root-2023" \ + csr=@pki_intermediate.csr \ + format=pem_bundle ttl="43800h" \ + | jq -r '.data.certificate' > capif_intermediate.cert.pem + + # Configurar la CA intermedia en Vault + vault write pki_int/intermediate/set-signed certificate=@capif_intermediate.cert.pem + + #Crear rol en Vault + vault write pki_int/roles/my-ca use_csr_common_name=true require_cn=false allowed_domains="*" allow_any_name=true allow_bare_domains=true allow_glob_domains=true allow_subdomains=true max_ttl=4300h ttl=4300h + + # Emitir un certificado firmado por la CA intermedia + # vault write -format=json pki_int/issue/my-ca \ + # common_name="nginx.mon.svc.cluster.local" \ + # format=pem_bundle ttl="438h" \ + # | jq -r '.data.certificate' > ccf_cert.crt.pem \ + # && jq -r '.data.issuing_ca' > root_ca.crt.pem \ + # && jq -r '.data.private_key' > private_key.pem + + # vault write -format=json pki_int/issue/my-ca \ + # common_name="nginx.mon.svc.cluster.local" \ + # format=pem_bundle ttl="438h" \ + # | jq -r '.data.private_key as $private_key | .data.issuing_ca as $issuing_ca | .data.certificate as $certificate | [$private_key, $issuing_ca, $certificate]' > cert_data.json + + + #Create CSR + openssl genrsa -out ./server.key 2048 + + cat > ./foo.cnf < cert_data.json + + vault write -format=json pki_int/sign/my-ca format=pem_bundle ttl="43000h" csr=@server.csr | jq -r '.data.issuing_ca as $issuing_ca | .data.certificate as $certificate | [$issuing_ca, $certificate]' > cert_data.json + + jq -r '.[0]' cert_data.json > root_ca.crt.pem + echo "### content root_ca.crt.pem ###" + cat root_ca.crt.pem + + echo "### content server_certificate.crt.pem ###" + jq -r '.[1]' cert_data.json > server_certificate.crt.pem + + openssl x509 -pubkey -noout -in server_certificate.crt.pem > server_certificate_pub.pem + + #vault kv put secret/ca ca=@root_ca.crt.pem root_2023_ca.crt + + #cat root_2023_ca.crt root_2023_ca.crt > ca.crt + + cat > certificados_concatenados.crt << EOF + $(cat "root_2023_ca.crt") + $(cat "root_ca.crt.pem") + EOF + echo "### content of root_2023_ca.crt ###" + cat root_2023_ca.crt + + echo "### content of root_ca.crt.pem ###" + cat root_ca.crt.pem + + echo "### content of certificados_concatenados.crt ###" + cat certificados_concatenados.crt + + # vault kv put secret/ca ca=@root_2023_ca.crt + + echo "### enable secrets kv ###" + vault secrets enable -path=secret -version=2 kv + + vault kv put secret/ca ca=@certificados_concatenados.crt + + vault kv put secret/server_cert cert=@server_certificate.crt.pem + + vault kv put secret/server_cert/pub pub_key=@server_certificate_pub.pem + + vault kv put secret/server_cert/private key=@server.key + + #POLICY_NAME="my-policy" + #POLICY_FILE="my-policy.hcl" + #TOKEN_ID="read-ca-token" + + # Crear la política en Vault + #echo "path \"secret/data/ca\" { + # capabilities = [\"read\"] + #}" > "$POLICY_FILE" + + #vault policy write "$POLICY_NAME" "$POLICY_FILE" + + # Generar un nuevo token y asignar la política + #TOKEN=$(vault token create -id="$TOKEN_ID" -policy="$POLICY_NAME" -format=json | jq -r '.auth.client_token') + + #echo "Token generado:" + #echo "$TOKEN" +--- + +apiVersion: batch/v1 +kind: Job +metadata: + name: vault-pki + namespace: mon + labels: + io.kompose.service: vault-pki + app: capif + app.kubernetes.io/name: capif + app.kubernetes.io/instance: capif +spec: + template: + spec: + containers: + - name: vault-pki + image: docker.io/hashicorp/vault:1.15.1 + command: ["./vault-prepare-certs.sh"] + volumeMounts: + - name: vault-prepare-certs + mountPath: vault-prepare-certs.sh + subPath: vault-prepare-certs.sh + restartPolicy: Never + volumes: + - name: vault-prepare-certs + configMap: + name: vault-prepare-certs + defaultMode: 0777 + items: + - key: "vault-prepare-certs.sh" + path: "vault-prepare-certs.sh" + backoffLimit: 4 diff --git a/monitoring/docker-compose.yml b/monitoring/docker-compose.yml new file mode 100644 index 0000000..41f647f --- /dev/null +++ b/monitoring/docker-compose.yml @@ -0,0 +1,110 @@ +version: '3' +services: + prometheus: + image: prom/prometheus:latest + container_name: prometheus + user: "${DUID}:${DGID}" + volumes: + - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml + - ./prometheus/prometheus_db:/var/lib/prometheus + - ./prometheus/prometheus_db:/prometheus + - ./prometheus/prometheus_db:/etc/prometheus + - ./prometheus/alert.rules:/etc/prometheus/alert.rules + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.route-prefix=/' + - '--storage.tsdb.retention.time=200h' + - '--web.enable-lifecycle' + restart: unless-stopped + ports: + - '9090:9090' + + # cadvisor collects metrics about running containers + cadvisor: + image: gcr.io/cadvisor/cadvisor:v0.47.2 + container_name: cadvisor + ports: + - 8090:8080 + volumes: + - /:/rootfs:ro + - /var/run:/var/run:rw + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /var/run/docker.sock:/var/run/docker.sock:rw + + grafana: + image: grafana/grafana + user: "${DUID}:${DGID}" + environment: + - GF_SECURITY_ADMIN_PASSWORD=secure_pass + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + volumes: + - ./grafana/grafana_config/grafana.ini:/etc/grafana/grafana.ini + - ./grafana/grafana_db:/var/lib/grafana + - ./grafana/grafana_provisioning/grafana-datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml + - ./grafana/grafana_provisioning/grafana-default-provisioning.yaml:/etc/grafana/provisioning/dashboards/default.yaml + - ./grafana/grafana_dashboards/Docker-monitoring.json:/var/lib/grafana/dashboards/Docker-monitoring.json + - ./grafana/grafana_dashboards/Loki-Logs.json:/var/lib/grafana/dashboards/Loki-Logs.json + + depends_on: + - prometheus + ports: + - '3000:3000' + + # loki save and analyze logs + loki: + image: grafana/loki:2.8.0 + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + + # promtail send docker logs to loki + promtail: + image: grafana/promtail:2.8.0 + volumes: + - /var/log:/var/log + command: -config.file=/etc/promtail/config.yml + + # grafana image renderer + renderer: + image: grafana/grafana-image-renderer:latest + container_name: grafana-image-renderer + expose: + - "8081" + environment: + ENABLE_METRICS: "true" + + # fluent-bit send logs to loki + fluent-bit: + image: grafana/fluent-bit-plugin-loki:latest + container_name: fluent-bit + environment: + - LOKI_URL=http://loki:3100/loki/api/v1/push + volumes: + - ./fluent_bit/fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf + ports: + - "24224:24224" + - "24224:24224/udp" + + # opentelemetry collector + otel-collector: + image: otel/opentelemetry-collector:latest + ports: + - 55680:55680 + - 4317:4317 + volumes: + - ./otlp_collector/otel-config.yaml:/etc/otel-collector-config.yaml + command: ["--config", "/etc/otel-collector-config.yaml"] + + # tempo is a distributed tracing backend + tempo: + image: grafana/tempo:latest + command: [ "-config.file=/etc/tempo.yaml" ] + volumes: + - ./tempo/tempo.yaml:/etc/tempo.yaml + - ./tempo/tempo-data:/tmp/tempo + ports: + - 3102:3100 + diff --git a/monitoring/fluent_bit/fluent-bit.conf b/monitoring/fluent_bit/fluent-bit.conf new file mode 100644 index 0000000..ab11a28 --- /dev/null +++ b/monitoring/fluent_bit/fluent-bit.conf @@ -0,0 +1,15 @@ +[INPUT] + Name forward + Listen 0.0.0.0 + Port 24224 +[Output] + Name grafana-loki + Match * + Url ${LOKI_URL} + RemoveKeys source + Labels {job="fluent-bit"} + LabelKeys container_name, traceID + BatchWait 1s + BatchSize 1001024 + LineFormat json + LogLevel info \ No newline at end of file diff --git a/monitoring/grafana/grafana_config/grafana.ini b/monitoring/grafana/grafana_config/grafana.ini new file mode 100644 index 0000000..c69fa95 --- /dev/null +++ b/monitoring/grafana/grafana_config/grafana.ini @@ -0,0 +1,1894 @@ +##################### Grafana Configuration Example ##################### +# +# Everything has defaults so you only need to uncomment things you want to +# change + +# possible values : production, development +;app_mode = production + +# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty +;instance_name = ${HOSTNAME} + +# force migration will run migrations that might cause dataloss +;force_migration = false + +#################################### Paths #################################### +[paths] +# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) +;data = /var/lib/grafana/dashboards + +# Temporary files in `data` directory older than given duration will be removed +;temp_data_lifetime = 24h + +# Directory where grafana can store logs +;logs = /var/log/grafana + +# Directory where grafana will automatically scan and look for plugins +;plugins = /var/lib/grafana/plugins + +# folder that contains provisioning config files that grafana will apply on startup and while running. +;provisioning = conf/provisioning + +#################################### Server #################################### +[server] +# Protocol (http, https, h2, socket) +;protocol = http + +# This is the minimum TLS version allowed. By default, this value is empty. Accepted values are: TLS1.2, TLS1.3. If nothing is set TLS1.2 would be taken +;min_tls_version = "" + +# The ip address to bind to, empty will bind to all interfaces +;http_addr = + +# The http port to use +;http_port = 3000 + +# The public facing domain name used to access grafana from a browser +;domain = localhost + +# Redirect to correct domain if host header does not match domain +# Prevents DNS rebinding attacks +;enforce_domain = false + +# The full public facing url you use in browser, used for redirects and emails +# If you use reverse proxy and sub path specify full url (with sub path) +;root_url = %(protocol)s://%(domain)s:%(http_port)s/ + +# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons. +;serve_from_sub_path = false + +# Log web requests +;router_logging = false + +# the path relative working path +;static_root_path = public + +# enable gzip +;enable_gzip = false + +# https certs & key file +;cert_file = +;cert_key = + +# Unix socket gid +# Changing the gid of a file without privileges requires that the target group is in the group of the process and that the process is the file owner +# It is recommended to set the gid as http server user gid +# Not set when the value is -1 +;socket_gid = + +# Unix socket mode +;socket_mode = + +# Unix socket path +;socket = + +# CDN Url +;cdn_url = + +# Sets the maximum time using a duration format (5s/5m/5ms) before timing out read of an incoming request and closing idle connections. +# `0` means there is no timeout for reading the request. +;read_timeout = 0 + +# This setting enables you to specify additional headers that the server adds to HTTP(S) responses. +[server.custom_response_headers] +#exampleHeader1 = exampleValue1 +#exampleHeader2 = exampleValue2 + +#################################### GRPC Server ######################### +;[grpc_server] +;network = "tcp" +;address = "127.0.0.1:10000" +;use_tls = false +;cert_file = +;key_file = + +#################################### Database #################################### +[database] +# You can configure the database connection by specifying type, host, name, user and password +# as separate properties or as on string using the url properties. + +# Either "mysql", "postgres" or "sqlite3", it's your choice +;type = sqlite3 +;host = 127.0.0.1:3306 +;name = grafana +;user = root +# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" +;password = + +# Use either URL or the previous fields to configure the database +# Example: mysql://user:secret@host:port/database +;url = + +# For "postgres", use either "disable", "require" or "verify-full" +# For "mysql", use either "true", "false", or "skip-verify". +;ssl_mode = disable + +# Database drivers may support different transaction isolation levels. +# Currently, only "mysql" driver supports isolation levels. +# If the value is empty - driver's default isolation level is applied. +# For "mysql" use "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ" or "SERIALIZABLE". +;isolation_level = + +;ca_cert_path = +;client_key_path = +;client_cert_path = +;server_cert_name = + +# For "sqlite3" only, path relative to data_path setting +;path = grafana.db + +# Max idle conn setting default is 2 +;max_idle_conn = 2 + +# Max conn setting default is 0 (mean not set) +;max_open_conn = + +# Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) +;conn_max_lifetime = 14400 + +# Set to true to log the sql calls and execution times. +;log_queries = + +# For "sqlite3" only. cache mode setting used for connecting to the database. (private, shared) +;cache_mode = private + +# For "sqlite3" only. Enable/disable Write-Ahead Logging, https://sqlite.org/wal.html. Default is false. +;wal = false + +# For "mysql" only if migrationLocking feature toggle is set. How many seconds to wait before failing to lock the database for the migrations, default is 0. +;locking_attempt_timeout_sec = 0 + +# For "sqlite" only. How many times to retry query in case of database is locked failures. Default is 0 (disabled). +;query_retries = 0 + +# For "sqlite" only. How many times to retry transaction in case of database is locked failures. Default is 5. +;transaction_retries = 5 + +# Set to true to add metrics and tracing for database queries. +;instrument_queries = false + +################################### Data sources ######################### +[datasources] +# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API. +;datasource_limit = 5000 + +#################################### Cache server ############################# +[remote_cache] +# Either "redis", "memcached" or "database" default is "database" +;type = database + +# cache connectionstring options +# database: will use Grafana primary database. +# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'. +# memcache: 127.0.0.1:11211 +;connstr = + +# prefix prepended to all the keys in the remote cache +; prefix = + +# This enables encryption of values stored in the remote cache +;encryption = + +#################################### Data proxy ########################### +[dataproxy] + +# This enables data proxy logging, default is false +;logging = false + +# How long the data proxy waits to read the headers of the response before timing out, default is 30 seconds. +# This setting also applies to core backend HTTP data sources where query requests use an HTTP client with timeout set. +;timeout = 30 + +# How long the data proxy waits to establish a TCP connection before timing out, default is 10 seconds. +;dialTimeout = 10 + +# How many seconds the data proxy waits before sending a keepalive probe request. +;keep_alive_seconds = 30 + +# How many seconds the data proxy waits for a successful TLS Handshake before timing out. +;tls_handshake_timeout_seconds = 10 + +# How many seconds the data proxy will wait for a server's first response headers after +# fully writing the request headers if the request has an "Expect: 100-continue" +# header. A value of 0 will result in the body being sent immediately, without +# waiting for the server to approve. +;expect_continue_timeout_seconds = 1 + +# Optionally limits the total number of connections per host, including connections in the dialing, +# active, and idle states. On limit violation, dials will block. +# A value of zero (0) means no limit. +;max_conns_per_host = 0 + +# The maximum number of idle connections that Grafana will keep alive. +;max_idle_connections = 100 + +# How many seconds the data proxy keeps an idle connection open before timing out. +;idle_conn_timeout_seconds = 90 + +# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request, default is false. +;send_user_header = false + +# Limit the amount of bytes that will be read/accepted from responses of outgoing HTTP requests. +;response_limit = 0 + +# Limits the number of rows that Grafana will process from SQL data sources. +;row_limit = 1000000 + +# Sets a custom value for the `User-Agent` header for outgoing data proxy requests. If empty, the default value is `Grafana/` (for example `Grafana/9.0.0`). +;user_agent = + +#################################### Analytics #################################### +[analytics] +# Server reporting, sends usage counters to stats.grafana.org every 24 hours. +# No ip addresses are being tracked, only simple counters to track +# running instances, dashboard and error counts. It is very helpful to us. +# Change this option to false to disable reporting. +;reporting_enabled = true + +# The name of the distributor of the Grafana instance. Ex hosted-grafana, grafana-labs +;reporting_distributor = grafana-labs + +# Set to false to disable all checks to https://grafana.com +# for new versions of grafana. The check is used +# in some UI views to notify that a grafana update exists. +# This option does not cause any auto updates, nor send any information +# only a GET request to https://raw.githubusercontent.com/grafana/grafana/main/latest.json to get the latest version. +;check_for_updates = true + +# Set to false to disable all checks to https://grafana.com +# for new versions of plugins. The check is used +# in some UI views to notify that a plugin update exists. +# This option does not cause any auto updates, nor send any information +# only a GET request to https://grafana.com to get the latest versions. +;check_for_plugin_updates = true + +# Google Analytics universal tracking code, only enabled if you specify an id here +;google_analytics_ua_id = + +# Google Analytics 4 tracking code, only enabled if you specify an id here +;google_analytics_4_id = + +# When Google Analytics 4 Enhanced event measurement is enabled, we will try to avoid sending duplicate events and let Google Analytics 4 detect navigation changes, etc. +;google_analytics_4_send_manual_page_views = false + +# Google Tag Manager ID, only enabled if you specify an id here +;google_tag_manager_id = + +# Rudderstack write key, enabled only if rudderstack_data_plane_url is also set +;rudderstack_write_key = + +# Rudderstack data plane url, enabled only if rudderstack_write_key is also set +;rudderstack_data_plane_url = + +# Rudderstack SDK url, optional, only valid if rudderstack_write_key and rudderstack_data_plane_url is also set +;rudderstack_sdk_url = + +# Rudderstack Config url, optional, used by Rudderstack SDK to fetch source config +;rudderstack_config_url = + +# Intercom secret, optional, used to hash user_id before passing to Intercom via Rudderstack +;intercom_secret = + +# Controls if the UI contains any links to user feedback forms +;feedback_links_enabled = true + +#################################### Security #################################### +[security] +# disable creation of admin user on first start of grafana +;disable_initial_admin_creation = false + +# default admin user, created on startup +;admin_user = admin + +# default admin password, can be changed before first start of grafana, or in profile settings +;admin_password = admin + +# default admin email, created on startup +;admin_email = admin@localhost + +# used for signing +;secret_key = SW2YcwTIb9zpOOhoPsMm + +# current key provider used for envelope encryption, default to static value specified by secret_key +;encryption_provider = secretKey.v1 + +# list of configured key providers, space separated (Enterprise only): e.g., awskms.v1 azurekv.v1 +;available_encryption_providers = + +# disable gravatar profile images +;disable_gravatar = false + +# data source proxy whitelist (ip_or_domain:port separated by spaces) +;data_source_proxy_whitelist = + +# disable protection against brute force login attempts +;disable_brute_force_login_protection = false + +# set to true if you host Grafana behind HTTPS. default is false. +;cookie_secure = false + +# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled" +;cookie_samesite = lax + +# set to true if you want to allow browsers to render Grafana in a ,