Skip to content

Commit

Permalink
Improve HTTPS connection tests
Browse files Browse the repository at this point in the history
  • Loading branch information
amotl committed Mar 25, 2021
1 parent 4f0b3a7 commit 9d309e1
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 31 deletions.
71 changes: 47 additions & 24 deletions src/crate/client/doctests/https.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,59 +23,82 @@ 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=clientcert_valid, key_file=clientcert_valid)
>>> 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=clientcert_invalid, key_file=clientcert_invalid)
>>> client.server_infos(crate_host)
Traceback (most recent call last):
...
crate.client.exceptions.ConnectionError: Server not available, exception: HTTPSConnectionPool...

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=clientcert_valid, key_file=clientcert_valid)
>>> client.server_infos(crate_host)
Traceback (most recent call last):
...
crate.client.exceptions.ConnectionError: Server not available, exception: ...[SSL: ...
crate.client.exceptions.ConnectionError: Server not available, exception: HTTPSConnectionPool...
File renamed without changes.
File renamed without changes.
45 changes: 45 additions & 0 deletions src/crate/client/pki/client_invalid.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwLzVfL66Z6GiuVVZsDMSuLQS8fnW402U0cNLJNp2resdswfC
y7t8X9KXi49nBCxn4RsNkWLQacdSxYhz5HTyuHny8id0Tb+05AY3yDvWIm7R+gXy
2tScqplcqotKCGLmPavQk1+H3ChderRVb7jTyphSx1n4bsdVSkbseajevz1afy07
D8kj/nhkGml7msZOrffjmxqgXLlC2tEuCnO7TA/KOn2uGLxoIivac7AqkRdnYB5j
3qVX2M6ftL8xAM2myNRuV+Ugj1XkvVE94/5Ihm1lKDqlwWh0dSzY0NnHwJh1ej98
V1er+bdbXOKEG6Pjjbk6xNHK0EtqonlUfgVX2QIDAQABAoIBADtygw6k7W3FZyFu
9+jm9+FMeYN1Ihid90bzy5ukXnKqUFDGFgks3OHZXLDJHGcnIytFYtvy9IGL3zXa
LpTKlYrc4lhaXv8UIEEswcva2ONp9w39A7kHVwMvpmtb5wvLJWTkN8Mc9hSrxplw
QeHhykF01iNy1rOke+QbGBk2Qu4M/1fRBUHcf+AWLamc3I6hE3Wy5GDZM3AGFVeW
jQB3E6EbPrvBfc8XVPoOwYbNnZYgF7H66Iya7IN0QjozKzE5RiX3dQXRnEIwIgcw
sJ3Nv8S8LgTIlumPMsvQHSRvVovT1/3V6uEsIrAUMVcXjv+Yuwp8z/Ux42deoToO
LR025vkCgYEA5y/6v3h0v4FpHHdsZQBJJdsaDyrFqdjpWO0VF2npH/ByITPNyZwy
whFSmXGTBFiIWQaleF00cwMNq0xxXDXRP2I/14TbM3DMXXznnCZoA4yROaoBd21Q
Ymo8N049DAVK3/AfFjFI1i7T7jAcrtVYX4kvU/3O8yP7WLCQnbPffKcCgYEA1Wxs
F7UyEznJBToLRTcaRiUUdqYcUt/JqmHlEC5BjpB939nGpLneulYz6WAlWdg8nMx7
zP2Iyk+ND0aSz0qjWuxSi0IZLF5JCbrRiKIgMO9F7yWw3T+gdmiezmLecxlExZ42
rfFI6o9AuG+0taY+nXu2oHbL0gJA6nLKWudgl38CgYBeYW0Jq+BlqixCLdL3rNUv
+jG6TWjivSYOYsOAioFcw6mkOmTh0L28EpxY/k/Zr1cCmT8GU26tIWr8KroAvgvN
x4turdNbPcqAxBQ94EQIZuOG2gu9OMhfVSV+Ipezh5mYsIvQYJBuuDFXBRdAnOJ2
JihHLs/E3USoYXS4nQ048wKBgA74ZPigwBtzITOZp7K6M8CZ1z6fVjtF8UpfRYcG
B5ktb3blOrbRRttBMrD7CoOr1EyXV1PAsPin7dgVdjTOInk9PGkCQOvIzUy+avYv
kRx9nCUzOp26WdIUcpc9ficKrbVC7Mj0tM2nML3/L+jR+XBofh3xV0iq2czYMnN/
6VmXAoGBAIUvnXaG5NXMBy2bs5j7NaHfizo5VM/4WIA6iB+dbuf6RcH18hG/C7Mf
RkOhVoTaQAS8FLg+0tMHKcxGMk8bcJcCKoFqD2+cOyyiPpaFXNpTg+VlHrtnH7s6
FCbwlfmb7RbpPI+iCYDtJQpoPvTeuC58mZTHvE5OQWchh32VuwzM
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC1DCCAj0CFGQC3tYjJ8bEqpzh37LH6gi+om8zMA0GCSqGSIb3DQEBCwUAMIGI
MQswCQYDVQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4x
IjAgBgNVBAoMGUNyw4PCpHRlIFRlY2hub2xvZ2llIEdtYkgxEzARBgNVBAMMCmxv
Y2FsaG9yc3QxHjAcBgkqhkiG9w0BCQEWD25vYm9keUBjcmF0ZS5pbzAeFw0yMTAz
MTkxODU0NTlaFw0yMjAzMTQxODU0NTlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQI
DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAvNV8vrpnoaK5VVmwMxK4
tBLx+dbjTZTRw0sk2nat6x2zB8LLu3xf0peLj2cELGfhGw2RYtBpx1LFiHPkdPK4
efLyJ3RNv7TkBjfIO9YibtH6BfLa1JyqmVyqi0oIYuY9q9CTX4fcKF16tFVvuNPK
mFLHWfhux1VKRux5qN6/PVp/LTsPySP+eGQaaXuaxk6t9+ObGqBcuULa0S4Kc7tM
D8o6fa4YvGgiK9pzsCqRF2dgHmPepVfYzp+0vzEAzabI1G5X5SCPVeS9UT3j/kiG
bWUoOqXBaHR1LNjQ2cfAmHV6P3xXV6v5t1tc4oQbo+ONuTrE0crQS2qieVR+BVfZ
AgMBAAEwDQYJKoZIhvcNAQELBQADgYEAFE+prZkMryCFqjELJWFPXfcxGIQmMP6U
mMCb1eny60s0mHu1TasqjxaoBN/1/PPi9ZGpWZfoI4UK/Xt+F6iFT2ehQvErXVop
cSAbGFSDH+ST6Qv5mE0Fzc1EPBa+x0qWzNeBBxUcQ89LH5cfX9HmuIFiErv9qr/K
ROJOkC6+AjU=
-----END CERTIFICATE-----
46 changes: 46 additions & 0 deletions src/crate/client/pki/client_valid.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEApEAgWEX1bWJWj5rCj0+BjbeaZdhzmNno43rYmwBBW+1U4BuD
bOuumnyfut3nns3e6mWcVvyc4F36a5CJt7b6YSxUi2k1fgrs08mzbOQaQ/dkiY+X
wdsMcb9Vdc+VHTK9dYwKQIbsTkWZ9zMPzZ0da8ilXGM8oHRyBZDrpRb4c18fWJpp
UMAmnStkm6FyWNEOug/FXFU4HduD/59z91SRpWaJX8HnbZcAOcMbXFomQ23rPPxi
Ld/rX86KwxPjTlZK3c3r7/eIN0iY/GqxZ+3Vx0W2I093Qai3XyAiSd1/HkJS19qP
f442evV03h+Y0zEVaPQ3+fxqvVc5aCzaQFl7jQIDAQABAoIBAALv8qQhfCYcoBep
WNlfPp3eLrCrkkWlf/ixdbYv5vtR3zayx0LnZBP3LpQU69N3MwlWD9muYs/QXm4W
A6B5cTjTph9oHkDGyT1wWfkUizOz9ORQ4RHibPKLzWdx8uS2x5SWkIhe4VL1A6/c
BehTavdGe06Pp8Hm0zMuSEiHhKHrhjpCLHyoWfUQV4wDdTQqGUtCm+vw9X//d4tr
rD7VtOj7EWxWekHAHBBuSutnydUgnYANdqmH23gz0ixQT0XFigO/pMZfjyQQImQp
yT+RpgUtM4KJQoGTEOcVloLfGrO9s/iJwhL9jcAypMA/VP1LXqp0tbYVgMwzTV9Y
EYtEYLECgYEAz+IAEPnGGPiL6wHwqXTZViszq4lL+BtNJGFRlSD0HfQsm1L7pIcO
f45Jy5f+cAQGRw2gbjal14107rQU9QoTiDUPyrs2wIItoEg+2IO7ujScqhQKpBwY
FMPfqTFp2yoRU4jOTj/1W16Vv6mIab8/AZGOjUC4djOUQBK3efCHBscCgYEAykS2
lAIK9N6o89fxLJO83PUbL/vom4qlMK4zu1dCzRk0KZe3tw41GlOWSUey0EJddNu1
WmkiRLypeRSRzlushvcD6bicoHj6G5ZtEWMgSUNSZhw03sJ9vvgyJR43ApFfXg4D
0h9ZyUD75YCWCj6t75694Ei6JteAOkjpYxP9RwsCgYACd8JccTqizUCL96ftuw9h
cH3aiXS3a0uNJQKc7Jk5Sc7FwURvfZL0fLHvksxYdBPHAChpZoiteGZs9wJQrl/w
/ABF/db2jhUQlAr68wVlfn5lnntJ23OFu5WKIqYJDgTKoxMf5q54+TR54/9Ukgqj
cCDrGFuYO6CE6jP3ZJ2VvQKBgF+rfIgpJzGHF3aujt48yrngHQnnJrBbNaL+4m0b
6vbDkw6ROk4VJDzdiFoE1aj3muio+vBWheTpL2ebuRNX/RShRXKI5VxpnDLsRY5R
ynWcqB6v/LnYWE25a05vKinGxMrh6iC6v2cXm42D8nPKDc8m0DyDabjxeS8YSXuZ
etTdAoGAH2keFYo3TPu1p7kgRXyJHeRFk4/n8N/jN+ChPZcOn9aZxBeOjwOAUTnu
QJsTv6mrzPlsUMVOhOnA9M3TebfgOhCbb7MJMT+e04mUgiACLwPMA7RVWyoVrivP
BD67yEKxqxKs5wh7kGIoUUsGaLLRCzRkrlIvBbUWcEh/sSEDEzA=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDJTCCAg0CFHFIksYWdXAiW8NROML2/iBbu/PrMA0GCSqGSIb3DQEBCwUAMFkx
CzAJBgNVBAYTAkFUMRMwEQYDVQQIDApWb3JhcmxiZXJnMREwDwYDVQQHDAhEb3Ju
YmlybjEOMAwGA1UECgwFQ3JhdGUxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yMTAz
MTkxOTE1MzhaFw0yMjAzMTQxOTE1MzhaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQI
DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkQCBYRfVtYlaPmsKPT4GN
t5pl2HOY2ejjetibAEFb7VTgG4Ns666afJ+63eeezd7qZZxW/JzgXfprkIm3tvph
LFSLaTV+CuzTybNs5BpD92SJj5fB2wxxv1V1z5UdMr11jApAhuxORZn3Mw/NnR1r
yKVcYzygdHIFkOulFvhzXx9YmmlQwCadK2SboXJY0Q66D8VcVTgd24P/n3P3VJGl
ZolfwedtlwA5wxtcWiZDbes8/GIt3+tfzorDE+NOVkrdzevv94g3SJj8arFn7dXH
RbYjT3dBqLdfICJJ3X8eQlLX2o9/jjZ69XTeH5jTMRVo9Df5/Gq9VzloLNpAWXuN
AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGQFf8I2V+wbWpTItkVMq9Mipb5b3z7w
aCpxyG2dB9MTKQ4wbrJ29q15g7GZjg9pmIzptJej9Vj7nYXuskeqeunMgwJUJ/QU
SUewx5MUYjl2cRtsAHXyQvqoV/FWwRqQGhqKGb3/dzULAgNYntIcXu+QNzOIA/q9
/Q4quG/SRcorKQM5RDbBpf8Lqan9csLNuL+u5T4BCYtqd7EaeHBMhQ30cP502Hn4
U0oYmnqvP2KNtvAPKhqKMWodd2MfyW87ifU7eugZFFY11y8HqvP5V3P0QxoxiBlB
XU6nnhHW88hel0gxFDZ51fbnVp6SP/hyjyt/deNaJzZfHFIPDqPXjLs=
-----END CERTIFICATE-----
File renamed without changes.
24 changes: 17 additions & 7 deletions src/crate/client/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ class HttpsTestServerLayer(object):
PORT = 65534
HOST = "localhost"
CERT_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__),
"test_https.pem"))
"pki/server_valid.pem"))
CACERT_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__),
"pki/cacert_valid.pem"))

__name__ = "httpsserver"
__bases__ = tuple()
Expand All @@ -223,6 +225,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

Expand Down Expand Up @@ -264,15 +267,22 @@ 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['valid_ca_cert'] = os.path.abspath(
os.path.join(os.path.dirname(__file__), "test_https_ca.pem")
)
test.globs['pprint'] = pprint
test.globs['print'] = cprint

test.globs['cacert_valid'] = os.path.abspath(
os.path.join(os.path.dirname(__file__), "pki/cacert_valid.pem")
)
test.globs['cacert_invalid'] = os.path.abspath(
os.path.join(os.path.dirname(__file__), "pki/cacert_invalid.pem")
)
test.globs['clientcert_valid'] = os.path.abspath(
os.path.join(os.path.dirname(__file__), "pki/client_valid.pem")
)
test.globs['clientcert_invalid'] = os.path.abspath(
os.path.join(os.path.dirname(__file__), "pki/client_invalid.pem")
)


def _try_execute(cursor, stmt):
try:
Expand Down

0 comments on commit 9d309e1

Please sign in to comment.