Skip to content

Commit 29333f8

Browse files
Windows Certificate Loading (#1460)
* Fix loading of certificate bundle on Windows * Remove skip marker --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent b3cbc41 commit 29333f8

File tree

4 files changed

+39
-7
lines changed

4 files changed

+39
-7
lines changed

newrelic/common/agent_http.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import os
16+
import ssl
1617
import sys
1718
import time
1819
import zlib
@@ -258,11 +259,28 @@ def __init__(
258259
if not ca_bundle_path:
259260
verify_path = get_default_verify_paths()
260261

261-
# If there is no resolved cafile, assume the bundled certs are
262-
# required and report this condition as a supportability metric.
263262
if not verify_path.cafile and not verify_path.capath:
264-
ca_bundle_path = certs.where()
265-
internal_metric("Supportability/Python/Certificate/BundleRequired", 1)
263+
if sys.platform != "win32":
264+
# If there is no resolved cafile on POSIX platforms, assume the bundled certs
265+
# are required and report this condition as a supportability metric.
266+
ca_bundle_path = certs.where()
267+
internal_metric("Supportability/Python/Certificate/BundleRequired", 1)
268+
else:
269+
# If there is no resolved cafile on Windows, attempt to load the default certs.
270+
try:
271+
_context = ssl.SSLContext()
272+
_context.load_default_certs()
273+
system_certs = _context.get_ca_certs()
274+
except Exception:
275+
system_certs = None
276+
277+
# If we still can't find any certs after loading the default ones,
278+
# then assume the bundled certs are required. If we do find them,
279+
# we don't have to do anything. We let urllib3 handle loading the
280+
# default certs from Windows.
281+
if not system_certs:
282+
ca_bundle_path = certs.where()
283+
internal_metric("Supportability/Python/Certificate/BundleRequired", 1)
266284

267285
if ca_bundle_path:
268286
if Path(ca_bundle_path).is_dir():

tests/agent_unittests/test_agent_protocol.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,12 @@ class DefaultVerifyPaths:
547547
def __init__(self, *args, **kwargs):
548548
pass
549549

550-
monkeypatch.setattr(ssl, "DefaultVerifyPaths", DefaultVerifyPaths)
550+
def get_ca_certs(purpose=None):
551+
return []
552+
553+
monkeypatch.setattr(ssl, "DefaultVerifyPaths", DefaultVerifyPaths) # Bypass OpenSSL default certs
554+
if sys.platform == "win32":
555+
monkeypatch.setattr(ssl.SSLContext, "get_ca_certs", get_ca_certs) # Bypass Windows default certs
551556

552557
settings = finalize_application_settings({"ca_bundle_path": ca_bundle_path})
553558
protocol = AgentProtocol(settings)

tests/agent_unittests/test_http_client.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import base64
1616
import json
1717
import ssl
18+
import sys
1819
import zlib
1920
from http.server import BaseHTTPRequestHandler, HTTPServer
2021
from io import StringIO
@@ -324,9 +325,11 @@ def test_default_cert_path(monkeypatch, system_certs_available):
324325
if system_certs_available:
325326
cert_file = "foo"
326327
ca_path = "/usr/certs"
328+
system_certs = [{"issuer": "Test CA"}] # Poorly faked certs
327329
else:
328330
cert_file = None
329331
ca_path = None
332+
system_certs = []
330333

331334
class DefaultVerifyPaths:
332335
cafile = cert_file
@@ -335,7 +338,13 @@ class DefaultVerifyPaths:
335338
def __init__(self, *args, **kwargs):
336339
pass
337340

338-
monkeypatch.setattr(ssl, "DefaultVerifyPaths", DefaultVerifyPaths)
341+
def get_ca_certs(purpose=None):
342+
return system_certs
343+
344+
monkeypatch.setattr(ssl, "DefaultVerifyPaths", DefaultVerifyPaths) # Bypass OpenSSL default certs
345+
if sys.platform == "win32":
346+
monkeypatch.setattr(ssl.SSLContext, "get_ca_certs", get_ca_certs) # Bypass Windows default certs
347+
339348
internal_metrics = CustomMetrics()
340349
with InternalTraceContext(internal_metrics):
341350
client = HttpClient("localhost", ca_bundle_path=None)

tests/cross_agent/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@
3131
app_name="Python Agent Test (cross_agent_tests)", default_settings=_default_settings
3232
)
3333

34-
SKIP_ON_WINDOWS = pytest.mark.xfail(sys.platform == "win32", reason="This feature is not supported on Windows")
34+
SKIP_ON_WINDOWS = pytest.mark.skipif(sys.platform == "win32", reason="This feature is not supported on Windows")

0 commit comments

Comments
 (0)