From e253eba5ed8922affe50089548a15fbda298fefd Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Mon, 12 Jul 2021 18:44:43 +0400 Subject: [PATCH] Stop abusing pytest-httpbin to test commonName support pytest-httpbin<1.0 ships with a server certificate with a commonName but no subjectAltName. urllib3 2.0 will stop supporting those in the future, so we want to upgrade pytest-httpbin. Unfortunately, `test_https_warnings` was relying on this broken certificate. With this change, we use `trustme` to create a broken certificate specifically for this test, so that we can upgrade pytest-httpbin and make sure that other tests relying on httpbin TLS support will continue to work with urllib3 2.0. --- requirements-dev.txt | 3 ++- tests/conftest.py | 34 ++++++++++++++++++++++++++++++++++ tests/test_requests.py | 6 +++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 600d4f4012..effb0c81f5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,8 @@ pytest>=2.8.0,<=3.10.1 pytest-cov -pytest-httpbin<1.0 +pytest-httpbin==1.0.0 pytest-mock==2.0.0 httpbin==0.7.0 Flask>=1.0,<2.0 +trustme wheel diff --git a/tests/conftest.py b/tests/conftest.py index cd64a7656a..099462cf52 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,19 @@ # -*- coding: utf-8 -*- +try: + from http.server import HTTPServer + from http.server import SimpleHTTPRequestHandler +except ImportError: + from BaseHTTPServer import HTTPServer + from SimpleHTTPServer import SimpleHTTPRequestHandler + +import ssl +import tempfile +import threading + import pytest from requests.compat import urljoin +import trustme def prepare_url(value): @@ -22,3 +34,25 @@ def httpbin(httpbin): @pytest.fixture def httpbin_secure(httpbin_secure): return prepare_url(httpbin_secure) + + +@pytest.fixture +def nosan_server(tmp_path_factory): + tmpdir = tmp_path_factory.mktemp("certs") + ca = trustme.CA() + # only commonName, no subjectAltName + server_cert = ca.issue_cert(common_name=u"localhost") + ca_bundle = str(tmpdir / "ca.pem") + ca.cert_pem.write_to_path(ca_bundle) + + context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + server_cert.configure_cert(context) + server = HTTPServer(("localhost", 0), SimpleHTTPRequestHandler) + server.socket = context.wrap_socket(server.socket, server_side=True) + server_thread = threading.Thread(target=server.serve_forever) + server_thread.start() + + yield "localhost", server.server_address[1], ca_bundle + + server.shutdown() + server_thread.join() diff --git a/tests/test_requests.py b/tests/test_requests.py index 8f3914ee22..b77cba007d 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -874,8 +874,9 @@ def test_http_with_certificate(self, httpbin): r = requests.get(httpbin(), cert='.') assert r.status_code == 200 - def test_https_warnings(self, httpbin_secure, httpbin_ca_bundle): + def test_https_warnings(self, nosan_server): """warnings are emitted with requests.get""" + host, port, ca_bundle = nosan_server if HAS_MODERN_SSL or HAS_PYOPENSSL: warnings_expected = ('SubjectAltNameWarning', ) else: @@ -885,8 +886,7 @@ def test_https_warnings(self, httpbin_secure, httpbin_ca_bundle): with pytest.warns(None) as warning_records: warnings.simplefilter('always') - requests.get(httpbin_secure('status', '200'), - verify=httpbin_ca_bundle) + requests.get("https://localhost:{}/".format(port), verify=ca_bundle) warning_records = [item for item in warning_records if item.category.__name__ != 'ResourceWarning']