diff --git a/datadog_sync/commands/shared/options.py b/datadog_sync/commands/shared/options.py index 3719eb91..cf0f9f7a 100644 --- a/datadog_sync/commands/shared/options.py +++ b/datadog_sync/commands/shared/options.py @@ -97,6 +97,16 @@ def click_config_file_provider(ctx: Context, opts: CustomOptionClass, value: Non help="Show or hide the progress bar", cls=CustomOptionClass, ), + option( + "--verify-ssl-certificates", + envvar=constants.DD_VERIFY_SSL_CERTIFICATES, + required=False, + type=bool, + default=True, + show_default=True, + help="Enable or disable SSL certificate verification. Warning: Disabling SSL verification is insecure.", + cls=CustomOptionClass, + ), option( "--verify-ddr-status", envvar=constants.DD_VERIFY_DDR_STATUS, diff --git a/datadog_sync/constants.py b/datadog_sync/constants.py index 3d23a171..c94af581 100644 --- a/datadog_sync/constants.py +++ b/datadog_sync/constants.py @@ -22,6 +22,7 @@ DD_VALIDATE = "DD_VALIDATE" DD_VERIFY_DDR_STATUS = "DD_VERIFY_DDR_STATUS" DD_SHOW_PROGRESS_BAR = "DD_SHOW_PROGRESS_BAR" +DD_VERIFY_SSL_CERTIFICATES = "DD_VERIFY_SSL_CERTIFICATES" LOCAL_STORAGE_TYPE = "local" S3_STORAGE_TYPE = "s3" diff --git a/datadog_sync/utils/configuration.py b/datadog_sync/utils/configuration.py index 57df0cda..26e20acf 100644 --- a/datadog_sync/utils/configuration.py +++ b/datadog_sync/utils/configuration.py @@ -140,20 +140,28 @@ def build_config(cmd: Command, **kwargs: Optional[Any]) -> Configuration: retry_timeout = kwargs.get("http_client_retry_timeout") timeout = kwargs.get("http_client_timeout") send_metrics = kwargs.get("send_metrics") + verify_ssl = kwargs.get("verify_ssl_certificates", True) source_auth = {} if k := kwargs.get("source_api_key"): source_auth["apiKeyAuth"] = k if k := kwargs.get("source_app_key"): source_auth["appKeyAuth"] = k - source_client = CustomClient(source_api_url, source_auth, retry_timeout, timeout, send_metrics) + source_client = CustomClient(source_api_url, source_auth, retry_timeout, timeout, send_metrics, verify_ssl) destination_auth = {} if k := kwargs.get("destination_api_key"): destination_auth["apiKeyAuth"] = k if k := kwargs.get("destination_app_key"): destination_auth["appKeyAuth"] = k - destination_client = CustomClient(destination_api_url, destination_auth, retry_timeout, timeout, send_metrics) + destination_client = CustomClient( + destination_api_url, + destination_auth, + retry_timeout, + timeout, + send_metrics, + verify_ssl, + ) # Additional settings force_missing_dependencies = kwargs.get("force_missing_dependencies") @@ -205,7 +213,14 @@ def build_config(cmd: Command, **kwargs: Optional[Any]) -> Configuration: # is just an import, the source of that import is the destination of the reset. if cmd == Command.RESET: cleanup = TRUE - source_client = CustomClient(destination_api_url, destination_auth, retry_timeout, timeout, send_metrics) + source_client = CustomClient( + destination_api_url, + destination_auth, + retry_timeout, + timeout, + send_metrics, + verify_ssl, + ) source_resources_path = f"{destination_resources_path}/.backup/{str(time.time())}" resource_per_file = kwargs.get(RESOURCE_PER_FILE, False) diff --git a/datadog_sync/utils/custom_client.py b/datadog_sync/utils/custom_client.py index 0cb1fd89..201e7f43 100644 --- a/datadog_sync/utils/custom_client.py +++ b/datadog_sync/utils/custom_client.py @@ -80,6 +80,7 @@ def __init__( retry_timeout: int, timeout: int, send_metrics: bool, + verify_ssl: bool = True, ) -> None: self.url_object = UrlObject.from_str(host) self.timeout = timeout @@ -88,10 +89,18 @@ def __init__( self.default_pagination = PaginationConfig() self.auth = auth self.send_metrics = send_metrics + self.verify_ssl = verify_ssl async def _init_session(self): - ssl_context = ssl.create_default_context(cafile=certifi.where()) - self.session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context)) + if self.verify_ssl: + ssl_context = ssl.create_default_context(cafile=certifi.where()) + self.session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context)) + else: + log.warning( + "WARNING: SSL certificate verification is disabled. " + "This is insecure and should only be used in trusted environments." + ) + self.session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) self.session.headers.update(build_default_headers(self.auth)) async def _end_session(self):