From bf11e6134422063bbe4bf4a347c6da115d1e464e Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Fri, 19 Mar 2021 17:50:06 +0100 Subject: [PATCH] Improve HTTPS connection tests --- src/crate/client/doctests/https.txt | 69 +++++++++++++++++++---------- src/crate/client/tests.py | 12 +++-- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/crate/client/doctests/https.txt b/src/crate/client/doctests/https.txt index 8e0210cf9..db7ce8bf7 100644 --- a/src/crate/client/doctests/https.txt +++ b/src/crate/client/doctests/https.txt @@ -23,58 +23,81 @@ with the path to the CA certificate file using the keyword argument :local: Examples --------- +======== -When switching on verification without a ``ca_cert`` file provided, the -connection will fail because we are using a self-signed server certificate:: +All of the following examples will connect to a host using a self-signed +certificate. - >>> verifying_client = HttpClient([crate_host]) - >>> verifying_client.server_infos(crate_host) + +With certificate verification +----------------------------- + +When using a valid CA certificate, the connection will be successful:: + + >>> client = HttpClient([crate_host], ca_cert=cacert_valid) + >>> client.server_infos(client._get_server()) + ('https://localhost:65534', 'test', '0.0.0') + +When not providing a ``ca_cert`` file, the connection will fail:: + + >>> client = HttpClient([crate_host]) + >>> client.server_infos(crate_host) Traceback (most recent call last): ... crate.client.exceptions.ConnectionError: Server not available, ...certificate verify failed... -Also, when providing an invalid ``ca_cert`` an error is raised:: +Also, when providing an invalid ``ca_cert``, an error is raised:: - >>> verifying_client = HttpClient([crate_host], ca_cert=invalid_ca_cert) - >>> verifying_client.server_infos(crate_host) + >>> client = HttpClient([crate_host], ca_cert=cacert_invalid) + >>> client.server_infos(crate_host) Traceback (most recent call last): ... crate.client.exceptions.ConnectionError: Server not available, ...certificate verify failed... -Connecting to a host whose certificate is verified with a valid CA certificate:: - >>> verifying_valid_client = HttpClient([crate_host], ca_cert=valid_ca_cert) - >>> verifying_valid_client.server_infos(verifying_valid_client._get_server()) - ('https://localhost:65534', 'test', '0.0.0') +Without certificate verification +-------------------------------- -When turning off certificate verification, calling the server will succeed:: +When turning off certificate verification, calling the server will succeed, +even when not providing a valid CA certificate:: - >>> non_verifying_client = HttpClient([crate_host], verify_ssl_cert=False) - >>> non_verifying_client.server_infos(crate_host) + >>> client = HttpClient([crate_host], verify_ssl_cert=False) + >>> client.server_infos(crate_host) ('https://localhost:65534', 'test', '0.0.0') Without verification, calling the server will even work when using an invalid ``ca_cert``:: - >>> non_verifying_client = HttpClient([crate_host], verify_ssl_cert=False, ca_cert=invalid_ca_cert) - >>> non_verifying_client.server_infos(crate_host) + >>> client = HttpClient([crate_host], verify_ssl_cert=False, ca_cert=cacert_invalid) + >>> client.server_infos(crate_host) ('https://localhost:65534', 'test', '0.0.0') + Client certificate ------------------ -The client supports client certificates. +The CrateDB driver also supports client certificates. The ``HttpClient`` constructor takes two keyword arguments: ``cert_file`` and -``key_file``. Both should be a string pointing to the path of the client -certificate and key file. +``key_file``. Both should be strings pointing to the path of the client +certificate and key file:: + + >>> client = HttpClient([crate_host], ca_cert=cacert_valid, cert_file=key_and_cert, key_file=key_and_cert, timeout=10) + >>> client.server_infos(crate_host) + ('https://localhost:65534', 'test', '0.0.0') + +When using an invalid client certificate, the connection will fail:: + + >>> client = HttpClient([crate_host], ca_cert=cacert_valid, cert_file=cacert_invalid, key_file=cacert_invalid, timeout=10) + >>> client.server_infos(crate_host) + Traceback (most recent call last): + ... + crate.client.exceptions.ConnectionError: Server not available, exception: ...[SSL: ... -This example uses that options, however it fails because the certificate is -invalid:: +The connection will also fail when providing an invalid CA certificate:: - >>> client = HttpClient([crate_host], cert_file=invalid_ca_cert, key_file=invalid_ca_cert, timeout=10) + >>> client = HttpClient([crate_host], ca_cert=cacert_invalid, cert_file=key_and_cert, key_file=key_and_cert, timeout=10) >>> client.server_infos(crate_host) Traceback (most recent call last): ... diff --git a/src/crate/client/tests.py b/src/crate/client/tests.py index ad1bbbde7..da19b4e5b 100644 --- a/src/crate/client/tests.py +++ b/src/crate/client/tests.py @@ -219,6 +219,8 @@ class HttpsTestServerLayer: HOST = "localhost" CERT_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), "test_https.pem")) + CACERT_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), + "test_https_ca.pem")) __name__ = "httpsserver" __bases__ = tuple() @@ -230,6 +232,7 @@ def get_request(self): keyfile=HttpsTestServerLayer.CERT_FILE, certfile=HttpsTestServerLayer.CERT_FILE, cert_reqs=ssl.CERT_OPTIONAL, + ca_certs=HttpsTestServerLayer.CACERT_FILE, server_side=True) return socket, client_address @@ -271,12 +274,15 @@ def setUpWithHttps(test): test.globs['crate_host'] = "https://{0}:{1}".format( HttpsTestServerLayer.HOST, HttpsTestServerLayer.PORT ) - test.globs['invalid_ca_cert'] = os.path.abspath( - os.path.join(os.path.dirname(__file__), "invalid_ca.pem") + test.globs['key_and_cert'] = os.path.abspath( + os.path.join(os.path.dirname(__file__), "test_https.pem") ) - test.globs['valid_ca_cert'] = os.path.abspath( + test.globs['cacert_valid'] = os.path.abspath( os.path.join(os.path.dirname(__file__), "test_https_ca.pem") ) + test.globs['cacert_invalid'] = os.path.abspath( + os.path.join(os.path.dirname(__file__), "invalid_ca.pem") + ) test.globs['pprint'] = pprint test.globs['print'] = cprint