Repository: getsentry/sentry-python

Issue:
Support for custom CA bundles
With the Raven client it is possible to [specify a custom CA bundle by appending the `ca_cert` parameter to the DSN](https://docs.sentry.io/clients/python/transports/). This is important for use of the client with on-premise installations of Sentry that use certificates signed by a custom CA. Sadly, [looking at `sentry_sdk.transport._make_pool`](https://github.com/getsentry/sentry-python/blob/30f339db3e76384e23fc951627c689197cb0e7d5/sentry_sdk/transport.py#L26), it seems this value is now hard-coded to `certifi.where()`. In result, users that previously used the `ca_cert` parameter are forced to stay on the Raven client. Thus, it would be great if you could (re-)add this feature.


Discussion:
Same story, this is essentially for us.

Logger shows this:
```
urllib3.connectionpool DEBUG    Starting new HTTPS connection (1): sentry:443
urllib3.util.retry DEBUG    Incremented Retry for (url='/api/4/store/'): Retry(total=2, connect=None, read=None, redirect=None, status=None)
urllib3.connectionpool WARNING  Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:579)'),)': /api/4/store/
```
Same for me. The workaround we used with raven was appending the (hard to find!)
`?ca_certs=/etc/ssl/certs/ca-cert-mycert.pem` option to the DSN, it doesn't work now and we cannot use the new sentry sdk.
Thanks, I will discuss it with the team. Ideally we would want to align the exact semantics and naming with other SDKs
@bpereto @marcosox @theMarix is there a reason why you can't install that certificate as a globally trusted one on your machine?
In our case we do have that certificate installed globally on the machines. It will work if you simply rely on the systems libopenssl. In fact, with Raven we actually set the `ca_path` to the system certificate bundle: `?ca_certs=/etc/ssl/certs/ca-certificates.crt"`. However, the code of the SDK explicitly uses the certificate bundle from the `certifi` package.
Ok thanks, figured out why we do this too. Will try to come up with something.

Resolving patch:
diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py
--- a/sentry_sdk/consts.py
+++ b/sentry_sdk/consts.py
@@ -27,6 +27,7 @@
     "before_breadcrumb": None,
     "debug": False,
     "attach_stacktrace": False,
+    "ca_certs": None,
 }
 
 
diff --git a/sentry_sdk/transport.py b/sentry_sdk/transport.py
--- a/sentry_sdk/transport.py
+++ b/sentry_sdk/transport.py
@@ -18,12 +18,16 @@
     from urllib import getproxies
 
 
-def _make_pool(parsed_dsn, http_proxy, https_proxy):
+def _make_pool(parsed_dsn, http_proxy, https_proxy, ca_certs):
     proxy = https_proxy if parsed_dsn == "https" else http_proxy
     if not proxy:
         proxy = getproxies().get(parsed_dsn.scheme)
 
-    opts = {"num_pools": 2, "cert_reqs": "CERT_REQUIRED", "ca_certs": certifi.where()}
+    opts = {
+        "num_pools": 2,
+        "cert_reqs": "CERT_REQUIRED",
+        "ca_certs": ca_certs or certifi.where(),
+    }
 
     if proxy:
         return urllib3.ProxyManager(proxy, **opts)
@@ -89,6 +93,7 @@ def __init__(self, options):
             self.parsed_dsn,
             http_proxy=options["http_proxy"],
             https_proxy=options["https_proxy"],
+            ca_certs=options["ca_certs"],
         )
         self._disabled_until = None
         self._retry = urllib3.util.Retry()


Test patch: