From 4fb51f2d03351197824d0641fb0fd26779458f1d Mon Sep 17 00:00:00 2001 From: Grammy Jiang <719388+grammy-jiang@users.noreply.github.com> Date: Fri, 12 Jul 2024 22:38:04 +1000 Subject: [PATCH] Add the client cert and key support to HttpTransport (#3258) * Add the client cert and key support to HttpTransport * Add a test case for the two-way ssl support in HttpTransport * Move cert_file and key_file to the end of arguments in ClientConstructor in consts.py --------- Co-authored-by: Neel Shah --- sentry_sdk/consts.py | 2 ++ sentry_sdk/transport.py | 13 ++++++++++--- tests/test_transport.py | 12 ++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 54de9d97e2..23920a2aa0 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -532,6 +532,8 @@ def __init__( enable_db_query_source=True, # type: bool db_query_source_threshold_ms=100, # type: int spotlight=None, # type: Optional[Union[bool, str]] + cert_file=None, # type: Optional[str] + key_file=None, # type: Optional[str] ): # type: (...) -> None pass diff --git a/sentry_sdk/transport.py b/sentry_sdk/transport.py index 63bd1d9fb3..e5c39c48e4 100644 --- a/sentry_sdk/transport.py +++ b/sentry_sdk/transport.py @@ -226,6 +226,8 @@ def __init__( http_proxy=options["http_proxy"], https_proxy=options["https_proxy"], ca_certs=options["ca_certs"], + cert_file=options["cert_file"], + key_file=options["key_file"], proxy_headers=options["proxy_headers"], ) @@ -474,8 +476,8 @@ def _send_envelope( ) return None - def _get_pool_options(self, ca_certs): - # type: (Optional[Any]) -> Dict[str, Any] + def _get_pool_options(self, ca_certs, cert_file=None, key_file=None): + # type: (Optional[Any], Optional[Any], Optional[Any]) -> Dict[str, Any] options = { "num_pools": self._num_pools, "cert_reqs": "CERT_REQUIRED", @@ -505,6 +507,9 @@ def _get_pool_options(self, ca_certs): or certifi.where() ) + options["cert_file"] = cert_file or os.environ.get("CLIENT_CERT_FILE") + options["key_file"] = key_file or os.environ.get("CLIENT_KEY_FILE") + return options def _in_no_proxy(self, parsed_dsn): @@ -524,6 +529,8 @@ def _make_pool( http_proxy, # type: Optional[str] https_proxy, # type: Optional[str] ca_certs, # type: Optional[Any] + cert_file, # type: Optional[Any] + key_file, # type: Optional[Any] proxy_headers, # type: Optional[Dict[str, str]] ): # type: (...) -> Union[PoolManager, ProxyManager] @@ -538,7 +545,7 @@ def _make_pool( if not proxy and (http_proxy != ""): proxy = http_proxy or (not no_proxy and getproxies().get("http")) - opts = self._get_pool_options(ca_certs) + opts = self._get_pool_options(ca_certs, cert_file, key_file) if proxy: if proxy_headers: diff --git a/tests/test_transport.py b/tests/test_transport.py index dc8e8073b5..5fc81d6817 100644 --- a/tests/test_transport.py +++ b/tests/test_transport.py @@ -165,6 +165,18 @@ def test_transport_num_pools(make_client, num_pools, expected_num_pools): assert options["num_pools"] == expected_num_pools +def test_two_way_ssl_authentication(make_client): + _experiments = {} + + client = make_client(_experiments=_experiments) + + options = client.transport._get_pool_options( + [], "/path/to/cert.pem", "/path/to/key.pem" + ) + assert options["cert_file"] == "/path/to/cert.pem" + assert options["key_file"] == "/path/to/key.pem" + + def test_socket_options(make_client): socket_options = [ (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),