diff --git a/README.md b/README.md index 6447b19..f9d8c58 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,8 @@ Log in to the Spring Boot Admin UI at `http://localhost:8080` to interact with t When registering a service in Spring Boot Admin, note that: * **Docker** - If the Spring Boot Admin is running in a container while the managed service is running in the docker-host directly, the `app_url` and `pyctuator_endpoint_url` should use `host.docker.internal` as the url's host so Spring Boot Admin will be able to connect to the monitored service. * **Http Traces** - In order for the "Http Traces" tab to be able to hide requests sent by Spring Boot Admin to the Pyctuator endpoint, `pyctuator_endpoint_url` must be using the same host and port as `app_url`. -* **HTTPS** - If Spring Boot Admin is using HTTPS with self-signed certificate, set the `PYCTUATOR_REGISTRATION_NO_CERT` environment variable so Pyctuator will disable certificate validation when registering (and deregistering). +* **HTTPS** - If Pyctuator is to be registered with Spring Boot Admin using HTTPS and the default SSL context is inappropriate, you can provide your own `ssl.SSLContext` using the `ssl_context` optional parameter of the `Pyctuator` constructor. +* **Insecure HTTPS** - If Spring Boot Admin is using HTTPS with self-signed certificate, set the `PYCTUATOR_REGISTRATION_NO_CERT` environment variable so Pyctuator will disable certificate validation when registering (and deregistering). ## Advanced Configuration The following sections are intended for advanced users who want to configure advanced Pyctuator features. diff --git a/pyctuator/impl/spring_boot_admin_registration.py b/pyctuator/impl/spring_boot_admin_registration.py index a117aa5..3d3aca2 100644 --- a/pyctuator/impl/spring_boot_admin_registration.py +++ b/pyctuator/impl/spring_boot_admin_registration.py @@ -25,7 +25,8 @@ def __init__( start_time: datetime, service_url: str, registration_interval_sec: float, - application_metadata: Optional[dict] = None + application_metadata: Optional[dict] = None, + ssl_context: Optional[ssl.SSLContext] = None, ) -> None: self.registration_url = registration_url self.registration_auth = registration_auth @@ -36,6 +37,7 @@ def __init__( self.registration_interval_sec = registration_interval_sec self.instance_id = None self.application_metadata = application_metadata if application_metadata else {} + self.ssl_context = ssl_context self.should_continue_registration_schedule: bool = False self.disable_certificate_validation_for_https_registration: bool = \ @@ -137,8 +139,8 @@ def _http_request(self, url: str, method: str, headers: Dict[str, str], body: Op if url_parts.scheme == "http": conn = http.client.HTTPConnection(url_parts.hostname, url_parts.port) elif url_parts.scheme == "https": - context = None - if self.disable_certificate_validation_for_https_registration: + context = self.ssl_context + if not context and self.disable_certificate_validation_for_https_registration: context = ssl.SSLContext() context.verify_mode = ssl.CERT_NONE conn = http.client.HTTPSConnection(url_parts.hostname, url_parts.port, context=context) diff --git a/pyctuator/pyctuator.py b/pyctuator/pyctuator.py index 860f510..2efdaca 100644 --- a/pyctuator/pyctuator.py +++ b/pyctuator/pyctuator.py @@ -2,6 +2,7 @@ import atexit import importlib.util import logging +import ssl from datetime import datetime, timezone from typing import Any, Optional, Dict, Callable @@ -40,6 +41,7 @@ def __init__( auto_deregister: bool = True, metadata: Optional[dict] = None, additional_app_info: Optional[dict] = None, + ssl_context: Optional[ssl.SSLContext] = None, ) -> None: """The entry point for integrating pyctuator with a web-frameworks such as FastAPI and Flask. @@ -76,6 +78,7 @@ def __init__( with SBA showing "offline" instances :param metadata: optional metadata key-value pairs that are displayed in SBA main page of an instance :param additional_app_info: additional arbitrary information to add to the application's "Info" section + :param ssl_context: optional SSL context to be used when registering with SBA """ self.auto_deregister = auto_deregister @@ -99,6 +102,7 @@ def __init__( self.boot_admin_registration_handler: Optional[BootAdminRegistrationHandler] = None self.metadata = metadata + self.ssl_context = ssl_context root_logger = logging.getLogger() # If application did not initiate logging module, add default handler to root logger @@ -130,7 +134,8 @@ def __init__( start_time, app_url, registration_interval_sec, - self.metadata + self.metadata, + self.ssl_context, ) # Deregister from SBA on exit