From a1311415ad5c868da77fbc885c6c349821c2c1c4 Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 10:29:50 +0200 Subject: [PATCH 1/8] !st pass using trustme --- tests/conftest.py | 68 +++-------------------------------------------- 1 file changed, 4 insertions(+), 64 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 8d743e3fb..c1a1511d2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,72 +1,12 @@ import pytest - -CERTIFICATE = b"""-----BEGIN CERTIFICATE----- -MIIEaDCCAtCgAwIBAgIRAPeU748qfVOTZJ7rj5DupbowDQYJKoZIhvcNAQELBQAw -fTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSkwJwYDVQQLDCBmcmFp -cjUwMEBmcmFpcjUwMC1QcmVjaXNpb24tNTUyMDEwMC4GA1UEAwwnbWtjZXJ0IGZy -YWlyNTAwQGZyYWlyNTAwLVByZWNpc2lvbi01NTIwMB4XDTE5MDEwOTIwMzQ1N1oX -DTI5MDEwOTIwMzQ1N1owVDEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNl -cnRpZmljYXRlMSkwJwYDVQQLDCBmcmFpcjUwMEBmcmFpcjUwMC1QcmVjaXNpb24t -NTUyMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALahGo80UFExe7Iv -jPDulPP9Vu3mPVW/4XhrvmbwjHPSXk6nvK34kdDmGsS/UVgtSMH+sdMNFavkhyK/ -b6PW5dPy+febfxlnaOkrZ5ptYx5IG1l/CNY/QDpQKGljW9YGQDV2t9apgKgT1/Ob -JIKf/rfd2o94iyxlrRnbXXidyMa1E6loo1AzzaN/g17dnblIL7ZCZtflgbsgnytw -UtwS92kTsvMHvuzM7Paz2M0xx+RNtQ2rq51fwph55gn7HLlBFEbkrMsfFj7hEquC -vJYvyrIEvaQLMyIOf+6/OgmrG9Z5ioMV4WAW9FLSuzXuuJruQc7FwQl4XIuE8d0M -jPjRfIcCAwEAAaOBizCBiDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYB -BQUHAwEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBTfMtd0Al3Ly09elEje6jyl -b3EQmjAyBgNVHREEKzApgglsb2NhbGhvc3SHBAAAAACHBH8AAAGHEAAAAAAAAAAA -AAAAAAAAAAEwDQYJKoZIhvcNAQELBQADggGBADLu7RSMVnUiRNyTqIM3aMmkUXmL -xSPB/SZRifqVwmp9R6ygAZWzC7Lw5BpX2WCde1jqWJZw1AjYbe4w5i8e9jaiUyYZ -eaLuQN7/+dyWeMIfFKx7thDxmati+OkSJSoojROA1v4NY7QAIM6ycfFkwTBRokPz -42srfR+XXrvdNmBRqjpvpr48SAn44uvqAkVr3kNgqs1xycPgjsFvMO7qZlU6w/ev -/7QFUgtyZS/Saa4s3yRXHZ++g3SpPinrzf8VqmovL/MoaqB/tYVjOA/1B3QAkli6 -DIl+99eKANlqARXzMeXvgLpcg+1oAw0hYjFpCtqKhovhQzqN6KlAbmJ9JWTk35x8 -81nOERZH5dh6JZoHzaaB/ZMEjWkmHnyi4bf5dXiPLzfXJslbQKHhnSt4nfZiSodS -brUVv/sux119zyUPe9iA6NNPFS/No1XOKcHrG19jiXTq/HIdJRoIrN6eRJDTRVK1 -HyJ6uTvTJDu4ceBp2J1gz7R5opWbGyytDGg3Tw== ------END CERTIFICATE----- -""" - -PRIVATE_KEY = b"""-----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2oRqPNFBRMXuy -L4zw7pTz/Vbt5j1Vv+F4a75m8Ixz0l5Op7yt+JHQ5hrEv1FYLUjB/rHTDRWr5Ici -v2+j1uXT8vn3m38ZZ2jpK2eabWMeSBtZfwjWP0A6UChpY1vWBkA1drfWqYCoE9fz -mySCn/633dqPeIssZa0Z2114ncjGtROpaKNQM82jf4Ne3Z25SC+2QmbX5YG7IJ8r -cFLcEvdpE7LzB77szOz2s9jNMcfkTbUNq6udX8KYeeYJ+xy5QRRG5KzLHxY+4RKr -gryWL8qyBL2kCzMiDn/uvzoJqxvWeYqDFeFgFvRS0rs17ria7kHOxcEJeFyLhPHd -DIz40XyHAgMBAAECggEAZ1q7Liob/icz6r5wU/WhhIduB8qSEZI65qyLH7Sot+9p -Abh51jbjRsbChXAEeBOAppEeT+OKzTHSrH6MjrtSa+WJQ3DTuCvGupae1k1rl7qV -B8wV0zIOhjHQ/PuHAJOfCOK73ZclwXkhcLLvMaGcRLAgPaupj6GnGggEWPtqodDo -qBOcixT3/lMW5M1GklkqJqbD8g8qcx7SFBwORJjpwVX84Ynnursu0ZvTfK/CzZTk -D5t/UXyRV5Y5QBkzKIKzC0qUHv4eMIqkzlPBYx2PnAgrHokOm9/RS28yKT2DVPhw -t311ZM6+Z5AxfKamARWZbZdC8RG5Qo0ujLmgogNn2QKBgQDsqpwO+/yJlvF81nf9 -0Ye5o0OdOdD5q1ra46PyhQ56hIC5cRZx3s3E9hUFDcot81qj9nMTpSGJL5J6GqAY -W7p3PbpYxT27MDjthgHHcZy7hu1M9no65ZAK1ElxVhKMgl89RQu/HQoa6Uh3qjbF -X0edTBTBJoGOYQ1lVaoL8s307QKBgQDFjGtEKubolZ0OqFb361fDcYs0RDKNlNxy -RIMM6Dhl0tgGHxNFuFNlLdjKyPEltfNaK0L0W3i3Ndf5sUlr2MuXYgO6RRqWo/D2 -Tr2/jd6gsVKLK871WD7IS5SbCirCwuEsZQsZ2J2TWECoPqc8L3iZwyW6VGRkIW+K -o2Sl7P4cwwKBgQCnhAt6P7p82S6NInFEY28iYwGU5DuavUNN9BszqiKZbfh/SiCM -8RvM8jHmpeAZrkrWC7dgjF20cMvJSddP5n2RsUuZUeNj/7oLxfK0bSJ3SgXlmADk -d2EBiUmCw13VvuISyDCMUc25Rq5YpU6nXc2e9R8rqEnDscZ9l6kJVA+b8QKBgBAZ -coB6spjP4J3aMERCJMPj1AFtcWVCdXjGhpudrUL3HO3ayHpNHFbJlrpoB+cX3f5C -OlGpxru/optRzHcCkw0CSuV6TkFqmO+p2SLsT/Fuohh/eH1cNLmkFzdPa861jR5O -GcqAcc8ZSSOs/3oTMFPvqHp3+DqE0w9MY552Ivt7AoGATtJkMAg9M4U/5qIsCbRz -LplSCRvcarrg+czXW1re6y117rVjRHPCHgT//azsBDER0WpWSGv7XEnZwnz8U6Cn -FCXoiqqEJuD2wLwQlhb7QVXYTMdCwfPj5WV7ARJO1N4ty3g8x+jnTQCVoMpdhgxC -Sflxx+6bI4XMh0AsZhgtdW4= ------END PRIVATE KEY----- -""" +import trustme @pytest.fixture(scope="function") def certfile_and_keyfile(tmp_path): + ca = trustme.CA() certfile = str(tmp_path / "cert.pem") - with open(certfile, "bw") as fout: - fout.write(CERTIFICATE) - + ca.cert_pem.write_to_path(certfile) keyfile = str(tmp_path / "key.pem") - with open(keyfile, "bw") as fout: - fout.write(PRIVATE_KEY) - + ca.private_key_pem.write_to_path(keyfile) return certfile, keyfile From 9e7ebfba89df20c7490d06f3d60367f06735ddd2 Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 10:31:48 +0200 Subject: [PATCH 2/8] 2nd pass with more precise fixtures --- tests/conftest.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index c1a1511d2..54e8eb000 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,11 +2,24 @@ import trustme +@pytest.fixture +def tls_certificate_authority(): + return trustme.CA() + + +@pytest.fixture +def tls_certificate(tls_certificate_authority): + return tls_certificate_authority.issue_server_cert( + 'localhost', + '127.0.0.1', + '::1', + ) + + @pytest.fixture(scope="function") -def certfile_and_keyfile(tmp_path): - ca = trustme.CA() +def certfile_and_keyfile(tls_certificate_authority, tmp_path): certfile = str(tmp_path / "cert.pem") - ca.cert_pem.write_to_path(certfile) + tls_certificate_authority.cert_pem.write_to_path(certfile) keyfile = str(tmp_path / "key.pem") - ca.private_key_pem.write_to_path(keyfile) + tls_certificate_authority.private_key_pem.write_to_path(keyfile) return certfile, keyfile From 6b6e8552e13c355b9335f1c4cbaf0782182ae0ff Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 10:36:05 +0200 Subject: [PATCH 3/8] 3rd pass --- tests/conftest.py | 17 ++++++++++------- tests/test_ssl.py | 7 +++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 54e8eb000..c56c1da82 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,10 +16,13 @@ def tls_certificate(tls_certificate_authority): ) -@pytest.fixture(scope="function") -def certfile_and_keyfile(tls_certificate_authority, tmp_path): - certfile = str(tmp_path / "cert.pem") - tls_certificate_authority.cert_pem.write_to_path(certfile) - keyfile = str(tmp_path / "key.pem") - tls_certificate_authority.private_key_pem.write_to_path(keyfile) - return certfile, keyfile +@pytest.fixture +def tls_ca_certificate_pem_path(tls_certificate_authority): + with tls_certificate_authority.cert_pem.tempfile() as ca_cert_pem: + yield ca_cert_pem + + +@pytest.fixture +def tls_ca_certificate_private_key_path(tls_certificate_authority): + with tls_certificate_authority.private_key_pem.tempfile() as private_key: + yield private_key diff --git a/tests/test_ssl.py b/tests/test_ssl.py index b83d7dde3..c29ac1f6d 100644 --- a/tests/test_ssl.py +++ b/tests/test_ssl.py @@ -28,8 +28,7 @@ def no_ssl_verification(session=requests.Session): @pytest.mark.skipif( sys.platform.startswith("win"), reason="Skipping SSL test on Windows" ) -def test_run(certfile_and_keyfile): - certfile, keyfile = certfile_and_keyfile +def test_run(tls_ca_certificate_pem_path, tls_ca_certificate_private_key_path): class App: def __init__(self, scope): @@ -48,8 +47,8 @@ def install_signal_handlers(self): app=App, loop="asyncio", limit_max_requests=1, - ssl_keyfile=keyfile, - ssl_certfile=certfile, + ssl_keyfile=tls_ca_certificate_private_key_path, + ssl_certfile=tls_ca_certificate_pem_path, ) server = CustomServer(config=config) thread = threading.Thread(target=server.run) From 992325503423edb2c74a7666af606d2a1ad66f82 Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 10:39:57 +0200 Subject: [PATCH 4/8] Forgot dev requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index fb7dde77c..2d49bd9c1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,6 +18,7 @@ pytest-cov pytest-mock requests mypy +trustme # Documentation mkdocs From cdf67522034576ef66c3bc576ccee166330677c5 Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 10:44:43 +0200 Subject: [PATCH 5/8] test updated + black --- tests/conftest.py | 6 +++--- tests/supervisors/test_watchgodreload.py | 2 +- tests/test_config.py | 9 ++++++--- tests/test_ssl.py | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index c56c1da82..e1f41fd0d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,9 +10,9 @@ def tls_certificate_authority(): @pytest.fixture def tls_certificate(tls_certificate_authority): return tls_certificate_authority.issue_server_cert( - 'localhost', - '127.0.0.1', - '::1', + "localhost", + "127.0.0.1", + "::1", ) diff --git a/tests/supervisors/test_watchgodreload.py b/tests/supervisors/test_watchgodreload.py index f8bc774fd..56aa53fc2 100644 --- a/tests/supervisors/test_watchgodreload.py +++ b/tests/supervisors/test_watchgodreload.py @@ -11,7 +11,7 @@ def run(sockets): pass -def test_watchgodreload(certfile_and_keyfile): +def test_watchgodreload(tls_ca_certificate_pem_path, tls_ca_certificate_private_key_path): config = Config(app=None) reloader = WatchGodReload(config, target=run, sockets=[]) reloader.signal_handler(sig=signal.SIGINT, frame=None) diff --git a/tests/test_config.py b/tests/test_config.py index d8052dc2e..3cebddb7e 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -84,9 +84,12 @@ def test_socket_bind(): assert isinstance(config.bind_socket(), socket.socket) -def test_ssl_config(certfile_and_keyfile): - certfile, keyfile = certfile_and_keyfile - config = Config(app=asgi_app, ssl_certfile=certfile, ssl_keyfile=keyfile) +def test_ssl_config(tls_ca_certificate_pem_path, tls_ca_certificate_private_key_path): + config = Config( + app=asgi_app, + ssl_certfile=tls_ca_certificate_pem_path, + ssl_keyfile=tls_ca_certificate_private_key_path, + ) config.load() assert config.is_ssl is True diff --git a/tests/test_ssl.py b/tests/test_ssl.py index c29ac1f6d..b43f86abb 100644 --- a/tests/test_ssl.py +++ b/tests/test_ssl.py @@ -29,7 +29,6 @@ def no_ssl_verification(session=requests.Session): sys.platform.startswith("win"), reason="Skipping SSL test on Windows" ) def test_run(tls_ca_certificate_pem_path, tls_ca_certificate_private_key_path): - class App: def __init__(self, scope): if scope["type"] != "http": From 7b535669a7d375a79df765f69576a52e7e7da179 Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 10:47:34 +0200 Subject: [PATCH 6/8] Black --- tests/supervisors/test_watchgodreload.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/supervisors/test_watchgodreload.py b/tests/supervisors/test_watchgodreload.py index 56aa53fc2..36a6e3261 100644 --- a/tests/supervisors/test_watchgodreload.py +++ b/tests/supervisors/test_watchgodreload.py @@ -11,7 +11,9 @@ def run(sockets): pass -def test_watchgodreload(tls_ca_certificate_pem_path, tls_ca_certificate_private_key_path): +def test_watchgodreload( + tls_ca_certificate_pem_path, tls_ca_certificate_private_key_path +): config = Config(app=None) reloader = WatchGodReload(config, target=run, sockets=[]) reloader.signal_handler(sig=signal.SIGINT, frame=None) From dc10e5afc96c31380e73a929bba231b4a6142dc0 Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 11:10:52 +0200 Subject: [PATCH 7/8] Added test to run uvicorn with a chain certificate ! --- tests/conftest.py | 8 +++++++- tests/test_ssl.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index e1f41fd0d..f396cb415 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,7 @@ @pytest.fixture -def tls_certificate_authority(): +def tls_certificate_authority() -> trustme.CA: return trustme.CA() @@ -26,3 +26,9 @@ def tls_ca_certificate_pem_path(tls_certificate_authority): def tls_ca_certificate_private_key_path(tls_certificate_authority): with tls_certificate_authority.private_key_pem.tempfile() as private_key: yield private_key + + +@pytest.fixture +def tls_certificate_pem_path(tls_certificate): + with tls_certificate.private_key_and_cert_chain_pem.tempfile() as cert_pem: + yield cert_pem diff --git a/tests/test_ssl.py b/tests/test_ssl.py index b43f86abb..e6b49367d 100644 --- a/tests/test_ssl.py +++ b/tests/test_ssl.py @@ -58,3 +58,37 @@ def install_signal_handlers(self): response = requests.get("https://127.0.0.1:8000") assert response.status_code == 204 thread.join() + + +@pytest.mark.skipif( + sys.platform.startswith("win"), reason="Skipping SSL test on Windows" +) +def test_run_chain(tls_certificate_pem_path): + class App: + def __init__(self, scope): + if scope["type"] != "http": + raise Exception() + + async def __call__(self, receive, send): + await send({"type": "http.response.start", "status": 204, "headers": []}) + await send({"type": "http.response.body", "body": b"", "more_body": False}) + + class CustomServer(Server): + def install_signal_handlers(self): + pass + + config = Config( + app=App, + loop="asyncio", + limit_max_requests=1, + ssl_certfile=tls_certificate_pem_path, + ) + server = CustomServer(config=config) + thread = threading.Thread(target=server.run) + thread.start() + while not server.started: + time.sleep(0.01) + with no_ssl_verification(): + response = requests.get("https://127.0.0.1:8000") + assert response.status_code == 204 + thread.join() From 556c3737ea13aa1323ddde525b2b9d272246ea79 Mon Sep 17 00:00:00 2001 From: euri10 Date: Wed, 7 Oct 2020 11:19:03 +0200 Subject: [PATCH 8/8] Added config test as well when using combined certificate and pk --- tests/test_config.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_config.py b/tests/test_config.py index 3cebddb7e..bd1c26873 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -95,6 +95,16 @@ def test_ssl_config(tls_ca_certificate_pem_path, tls_ca_certificate_private_key_ assert config.is_ssl is True +def test_ssl_config_combined(tls_certificate_pem_path): + config = Config( + app=asgi_app, + ssl_certfile=tls_certificate_pem_path, + ) + config.load() + + assert config.is_ssl is True + + def asgi2_app(scope): async def asgi(receive, send): pass