Skip to content

Commit

Permalink
Add SSL tests
Browse files Browse the repository at this point in the history
To run SSL tests, use Tarantool Enterprise 2.10 or newer and set
TEST_TT_SSL=TRUE flag. The patch is based on similar patch in
tarantool/tarantool-python connector [1].

1. tarantool/tarantool-python#220

Follows up igorcoding#22
  • Loading branch information
DifferentialOrange committed Aug 11, 2022
1 parent 0e9b087 commit 205bb67
Show file tree
Hide file tree
Showing 7 changed files with 386 additions and 0 deletions.
20 changes: 20 additions & 0 deletions tests/files/ssl/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDLzCCAhegAwIBAgIUMwa7m6dtjVYPK5iZAMX8YUuHtxEwDQYJKoZIhvcNAQEL
BQAwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD0V4YW1wbGUtUm9vdC1DQTAeFw0y
MjA2MTYwODQzMThaFw00NDExMTkwODQzMThaMCcxCzAJBgNVBAYTAlVTMRgwFgYD
VQQDDA9FeGFtcGxlLVJvb3QtQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC923p9pD1ajiAPsM2W6cnjSkexHX2+sJeaLXL6zdFeUjLYRAnfzJ9xVih7
91yWbuJ9OAswWmz83JrtSm1GqZpFucSz5pFqW2AVrhX5TezlxyH9QwPl+Scu1kCd
+wu7Fgkuw7a0SOpYafPQ6smucCWbxkyZTNgysNuWswykal4VCWyekaY/OojEImoG
smGOXe1Pr2x8XsiWVau1UJ0jj/vh5VzF05mletaUOoQ+iorIHAfnOm2K53jAZlNG
X83VJ1ijSDwiKcnFKcQqlq2Zt88UpxMMv0UyFbDCrOj5qfBbAvzZj5IgUi/NvoZz
M+lzwT+/0mADkAHB6EVa4R29zM+fAgMBAAGjUzBRMB0GA1UdDgQWBBSloRx6dBUI
gJb0yzP2c5zQdQQ+2TAfBgNVHSMEGDAWgBSloRx6dBUIgJb0yzP2c5zQdQQ+2TAP
BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCCUEnzpu8hZAckICLR
5JRDUiHJ3yJ5iv0b9ChNaz/AQBQGRE8bOPC2M/ZG1RuuQ8IbRbzK0fy1ty9KpG2D
JC9iDL6zPOC3e5x2H8Gxbhvjz4QnHPbYTfdJSmX5tJyNIrJ77g4SW5g8eFApTHyY
5KwRD3IDEu4pZNGsM7l0ODBC/4lvR8u7wPJDGyJBpE3uAKC20XqbG8BWm3kPb9+T
wE4Ak/FEXcwARB0fJ6Jni9iK3TeReyB3rpsYJa4N9iY6f1qNy4qQZ8Va6EWPSNnB
FhvCIYt4LdgM9ffUuHPrCX7qdgSNiL4VijgLaEHjFUUlLb6NHgQfYx/JG7wstiKs
Syzb
-----END CERTIFICATE-----
Empty file added tests/files/ssl/empty
Empty file.
35 changes: 35 additions & 0 deletions tests/files/ssl/generate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -xeuo pipefail
# An example how-to re-generate testing certificates (because usually
# TLS certificates have expiration dates and some day they will expire).
#
# The instruction is valid for:
#
# $ openssl version
# OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)

cat <<EOF > domains_localhost.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
EOF

cat <<EOF > domains_invalidhost.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = invalidhostname
EOF

openssl req -x509 -nodes -new -sha256 -days 8192 -newkey rsa:2048 -keyout ca.key -out ca.pem -subj "/C=US/CN=Example-Root-CA"
openssl x509 -outform pem -in ca.pem -out ca.crt

openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost"
openssl x509 -req -sha256 -days 8192 -in localhost.csr -CA ca.pem -CAkey ca.key -CAcreateserial -extfile domains_localhost.ext -out localhost.crt
openssl x509 -req -sha256 -days 8192 -in localhost.csr -CA ca.pem -CAkey ca.key -CAcreateserial -extfile domains_invalidhost.ext -out invalidhost.crt
22 changes: 22 additions & 0 deletions tests/files/ssl/invalidhost.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDkjCCAnqgAwIBAgIUV7NbprG6FEvrSP0kZ7pT9s7eN7swDQYJKoZIhvcNAQEL
BQAwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD0V4YW1wbGUtUm9vdC1DQTAeFw0y
MjA2MTYwODQzMThaFw00NDExMTkwODQzMThaMGcxCzAJBgNVBAYTAlVTMRIwEAYD
VQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MR0wGwYDVQQKDBRFeGFt
cGxlLUNlcnRpZmljYXRlczESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqGqKNkOVMGeIClmjLRf02UhtpYcGYVmiblpB
rqbI7eXKKIXMm4ppEEC/1YMVx/iYNYUK0xXxtzZUe1R6L5PYKAm1X+EQ4Sipyj/s
J+qsHxC65mavKB0ylZLZxAjZbiqBBYWwt0uz6ihHAtNXmoBzCE/mTRI3vTOd+CGQ
EI5pLGB85UuyvTfMKFwV9cTfltqGNyAZ670TFxtIwLeGuExfAFTVyofFWb8Kniby
EwKm/1giFl0HrKsHzPljKjlug6lcUeGxooTUJ9sxe6zPYGy2c6EqyV62/UVzgxv9
LNejeh3vlFmQbeawrwvQSMNi+sVuiaYmq/FIw5e4pUYUTjf+SQIDAQABo3YwdDAf
BgNVHSMEGDAWgBSloRx6dBUIgJb0yzP2c5zQdQQ+2TAJBgNVHRMEAjAAMAsGA1Ud
DwQEAwIE8DAaBgNVHREEEzARgg9pbnZhbGlkaG9zdG5hbWUwHQYDVR0OBBYEFNpJ
/WkoMwKCdo0w0HV8aYm1m7ayMA0GCSqGSIb3DQEBCwUAA4IBAQC2tCfqPF2QrieZ
5632SyuX9oDzBCPQv2vi68QRtL+VxjmJ+IPLHdpZ96jTM7pYIAQ5QVm357JXLixU
NJ0eqgGIFrY4Evx91AGEAX20Ccn8CCXK3LsG1z1UWrvH/txEyOecuLCukaDI5ejq
z1/CKJhxF7bBfukfG2X8qWqqUNRQpkdQObMwZ6Np/GhITIDldxRMIaP05pUGPybR
CrEiC5F5lwgVAwlNhnfJuBcH3XMKWFZuiyur3O6PfSmUByainSnLY94RefofyEct
t20ikQssE6XcX/soTtmwOvIGHHMGcuKBbTwlF0dxv9pLrikpXrv0sf3mT+abUqND
oPmVcDJp
-----END CERTIFICATE-----
22 changes: 22 additions & 0 deletions tests/files/ssl/localhost.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDkjCCAnqgAwIBAgIUI7y4bpqOVjvp9aEzUlsSO4pZgjAwDQYJKoZIhvcNAQEL
BQAwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD0V4YW1wbGUtUm9vdC1DQTAeFw0y
MjA2MTYwODQzMThaFw00NDExMTkwODQzMThaMGcxCzAJBgNVBAYTAlVTMRIwEAYD
VQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MR0wGwYDVQQKDBRFeGFt
cGxlLUNlcnRpZmljYXRlczESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqGqKNkOVMGeIClmjLRf02UhtpYcGYVmiblpB
rqbI7eXKKIXMm4ppEEC/1YMVx/iYNYUK0xXxtzZUe1R6L5PYKAm1X+EQ4Sipyj/s
J+qsHxC65mavKB0ylZLZxAjZbiqBBYWwt0uz6ihHAtNXmoBzCE/mTRI3vTOd+CGQ
EI5pLGB85UuyvTfMKFwV9cTfltqGNyAZ670TFxtIwLeGuExfAFTVyofFWb8Kniby
EwKm/1giFl0HrKsHzPljKjlug6lcUeGxooTUJ9sxe6zPYGy2c6EqyV62/UVzgxv9
LNejeh3vlFmQbeawrwvQSMNi+sVuiaYmq/FIw5e4pUYUTjf+SQIDAQABo3YwdDAf
BgNVHSMEGDAWgBSloRx6dBUIgJb0yzP2c5zQdQQ+2TAJBgNVHRMEAjAAMAsGA1Ud
DwQEAwIE8DAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwHQYDVR0OBBYEFNpJ
/WkoMwKCdo0w0HV8aYm1m7ayMA0GCSqGSIb3DQEBCwUAA4IBAQC2UFwSoqAMfg1h
xhYauemq13+JXPOnfoR74WzJc8Wva51Bqr8YpVxXU8GCViZKdWi/6sT5h//M4Zrp
wmcUruAQinRUy7RzKoXFHL7g6hQOE440gqaePE/PvjTde8l7FeiGTCSfAqIIFpsz
8YhVajenrzt9ppaHnad/N59uCnIULZrezRq8wJl8Zw82IR/Szcu/4O/tSimYuleY
pNX1h5w2mfpNmKeXkseU8cid1GhCnBg2FK6t6xZ4sSCL2nlpNKsbYvLg5rViRavO
7roUcU4BKK5NnGuYOPKYycSpC500V+shnCq4vTZSsPTOT2dHdMMK5HguxzHxixQv
yPeWBYqy
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions tests/files/ssl/localhost.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCoaoo2Q5UwZ4gK
WaMtF/TZSG2lhwZhWaJuWkGupsjt5coohcybimkQQL/VgxXH+Jg1hQrTFfG3NlR7
VHovk9goCbVf4RDhKKnKP+wn6qwfELrmZq8oHTKVktnECNluKoEFhbC3S7PqKEcC
01eagHMIT+ZNEje9M534IZAQjmksYHzlS7K9N8woXBX1xN+W2oY3IBnrvRMXG0jA
t4a4TF8AVNXKh8VZvwqeJvITAqb/WCIWXQesqwfM+WMqOW6DqVxR4bGihNQn2zF7
rM9gbLZzoSrJXrb9RXODG/0s16N6He+UWZBt5rCvC9BIw2L6xW6Jpiar8UjDl7il
RhRON/5JAgMBAAECggEAHWxlorbadvcziYlhDIUJsjdo7pkhOHtSOUDcBlEdvBBg
KgW8OjVrhxsk2L7a3JG2N+17N2c3UGi1yEk5QpwsEMynay2VRx0VUuApmEyzzwab
fJrWgaXeO0sJcCoSoKBc47PYbKGVeHSaeWgmfzfvQPXCmNb0tYGx2NK2Smoy/j1B
lXgODPkXHuzj0LOA3OkapgrxqHpN+kPjAfaY8vKYBQ8lbROT3kjgjqEzykC3bCzj
ZNZArGovBRAGr7dvjdh791g3hN2cAgIWhTg4zu8N6gf18G1l4bH8nmRzWT/z7eJi
QvmGjXVPUEpBcWRZuHms5cGcxb7V6smvuJp4v1n+rQKBgQDa1rqNwVlk1Jo0oT5U
KUyJwjaVXa3Foy5oR/T66UDIEBiMEonfI/miMlwXRXdhC1WQTeddk5vX+pn3ISZT
mN6zwz2NGE1i4GmOLIG9a9JkCSPffqDiwYFd2uhbTfKNehIHOC4Xdg/UGz+vOGFZ
MxYiSrytYK6svgHjHlFPp/uP9QKBgQDFA9wVmE76FqVC7crA7Djkyt4cRU5LEILO
qp4AxWE8HU/vlht4PhVA/dgMTNkVLiyrSgTGm15FQKZWe2FMVaAnRcmLy6bRpcAM
fP4HNtwjRWHx1Q4lMRZLrZPO0W8RXUqgMgGd3w1kyJK/C9wnD/01h+3lAnJ1cHlD
5jub6RDkhQKBgQCUciSKFCY3p6ATI23MWVd5+yxblfhSoKbSRj2AFsnC7Gg6XDj6
DMVBqTee8ZhRVAbupGnVqFOG5o+ae/orqv8mocIW++1CrUftEXPQsls9UJXs/VDV
gL3olJ4ZkX5/SdcA3rMlZwjFsNY6XdxrTaQuDtR+J59Vvm45Sk+N4T1cIQKBgG9d
zSzP2eT4pBZ/QJtpbIe4PXGRo74+6RJV09bvvBU1JJh0K7b+sRj55QSe9B9K6Kky
wBxcex9+eghs2gVCabOJeXJyfiwIG9VzWk1Nr4aok8MWAlb3tni099ZzAOu55pND
cTKCgZm0327rD1ltal62Jb3MclL8by/4lz18s7XZAoGBANSv/AdjlJUQ++9I+P1+
g7rgrfWKLyQ8FSljO7dAOWsDjrFHSi2f2HCh3URcKqzdjG+/iK+MyKUlaUZDLCzf
QNgI+7n5I/aHfhRWo7ytRPTd78Gyw/lDGW3Pz8MzXJ4pVDgr2UB7KN91/Rx9dJfN
3K04YR/TSpwB0Nug+5a1XuGh
-----END PRIVATE KEY-----
259 changes: 259 additions & 0 deletions tests/test_ssl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
import asyncio
import unittest
import os

import asynctnt
from asynctnt.exceptions import SSLError
from asynctnt.instance import TarantoolSyncInstance
from tests import BaseTarantoolTestCase

def is_test_ssl():
env = os.getenv("TEST_TT_SSL")
if env:
env = env.upper()
return env == "1" or env == "TRUE"
return False


@unittest.skipIf(not is_test_ssl(), "TEST_TT_SSL is not set.")
class SSLTestCase(BaseTarantoolTestCase):
DO_CONNECT = False

ssl_files_dir = os.path.join(os.getcwd(), 'tests', 'files', 'ssl')
cert_file = os.path.join(ssl_files_dir, "localhost.crt")
invalidhost_cert_file = os.path.join(ssl_files_dir, "invalidhost.crt")
key_file = os.path.join(ssl_files_dir, "localhost.key")
ca_file = os.path.join(ssl_files_dir, "ca.crt")
empty_file = os.path.join(ssl_files_dir, "empty")
invalid_file = "any_invalid_path"

async def test__connect(self):
if self.in_docker:
self.skipTest('Skipping as running inside the docker')
return

class SslTestSubcase:
def __init__(self,
name="",
expectSSLError=False,
expectTimeoutError=False,
server_transport=asynctnt.Transport.SSL,
server_key_file=None,
server_cert_file=None,
server_ca_file=None,
server_ciphers=None,
client_transport=asynctnt.Transport.SSL,
client_cert_file=None,
client_key_file=None,
client_ca_file=None,
client_ciphers=None):
self.name = name
self.expectSSLError = expectSSLError
self.expectTimeoutError = expectTimeoutError
self.server_transport = server_transport
self.server_key_file = server_key_file
self.server_cert_file = server_cert_file
self.server_ca_file = server_ca_file
self.server_ciphers = server_ciphers
self.client_transport = client_transport
self.client_cert_file = client_cert_file
self.client_key_file = client_key_file
self.client_ca_file = client_ca_file
self.client_ciphers = client_ciphers

# Requirements from Tarantool Enterprise Edition manual:
# https://www.tarantool.io/en/enterprise_doc/security/#configuration
#
# For a server:
# ssl_key_file - mandatory
# ssl_cert_file - mandatory
# ssl_ca_file - optional
# ssl_ciphers - optional
#
# For a client:
# ssl_key_file - optional, mandatory if server.CaFile set
# ssl_cert_file - optional, mandatory if server.CaFile set
# ssl_ca_file - optional
# ssl_ciphers - optional
testcases = [
SslTestSubcase(
name="no_ssl_server",
expectSSLError=True,
server_transport=asynctnt.Transport.DEFAULT),
SslTestSubcase(
name="key_crt_server",
server_key_file=self.key_file,
server_cert_file=self.cert_file),
SslTestSubcase(
name="no_ssl_client",
expectTimeoutError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
client_transport=asynctnt.Transport.DEFAULT),
SslTestSubcase(
name="key_crt_server_and_client",
server_key_file=self.key_file,
server_cert_file=self.cert_file,
client_key_file=self.key_file,
client_cert_file=self.cert_file),
SslTestSubcase(
name="key_crt_ca_server",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file),
SslTestSubcase(
name="key_crt_ca_server_and_crt_client",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_cert_file=self.cert_file),
SslTestSubcase(
name="key_crt_ca_server_and_key_crt_client",
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_key_file=self.key_file,
client_cert_file=self.cert_file),
SslTestSubcase(
name="key_crt_ca_server_and_client",
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_key_file=self.key_file,
client_cert_file=self.cert_file,
client_ca_file=self.ca_file),
SslTestSubcase(
name="key_invalidhost_crt_ca_server_and_key_crt_ca_client",
# A Tarantool implementation does not check hostname. It's
# the expected behavior. We don't do that too.
server_key_file=self.key_file,
server_cert_file=self.invalidhost_cert_file,
server_ca_file=self.ca_file,
client_key_file=self.key_file,
client_cert_file=self.cert_file,
client_ca_file=self.ca_file),
SslTestSubcase(
name="key_crt_ca_server_and_client_invalid_crt",
expectSSLError=True,
client_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
server_key_file=self.key_file,
client_cert_file=self.invalid_file,
client_ca_file=self.ca_file),
SslTestSubcase(
name="key_crt_ca_server_and_client_invalid_key",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_key_file=self.invalid_file,
client_cert_file=self.cert_file,
client_ca_file=self.ca_file),
SslTestSubcase(
name="key_crt_ca_server_and_client_invalid_ca",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_key_file=self.key_file,
client_cert_file=self.cert_file,
client_ca_file=self.invalid_file),
SslTestSubcase(
name="key_crt_ca_server_and_client_empty_crt",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_key_file=self.key_file,
client_cert_file=self.empty_file,
client_ca_file=self.ca_file),
SslTestSubcase(
name="key_crt_ca_server_and_client_empty_key",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_key_file=self.empty_file,
client_cert_file=self.cert_file,
client_ca_file=self.ca_file),
SslTestSubcase(
name="key_crt_ca_server_and_client_empty_ca",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
client_key_file=self.key_file,
client_cert_file=self.cert_file,
client_ca_file=self.empty_file),
SslTestSubcase(
name="key_crt_ca_ciphers_server_and_key_crt_ca_client",
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
server_ciphers="ECDHE-RSA-AES256-GCM-SHA384",
client_key_file=self.key_file,
client_cert_file=self.cert_file,
client_ca_file=self.ca_file),
SslTestSubcase(
name="key_crt_ca_ciphers_server_and_client",
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
server_ciphers="ECDHE-RSA-AES256-GCM-SHA384",
client_key_file=self.key_file,
client_cert_file=self.cert_file,
client_ca_file=self.ca_file,
client_ciphers="ECDHE-RSA-AES256-GCM-SHA384"),
SslTestSubcase(
name="non_equal_ciphers",
expectSSLError=True,
server_key_file=self.key_file,
server_cert_file=self.cert_file,
server_ca_file=self.ca_file,
server_ciphers="ECDHE-RSA-AES256-GCM-SHA384",
client_key_file=self.key_file,
client_cert_file=self.cert_file,
client_ca_file=self.ca_file,
client_ciphers="TLS_AES_128_GCM_SHA256"),
]

for t in testcases:
with self.subTest(msg=t.name):
tnt = TarantoolSyncInstance(
port=TarantoolSyncInstance.get_random_port(),
transport=t.server_transport,
ssl_key_file=t.server_key_file,
ssl_cert_file=t.server_cert_file,
ssl_ca_file=t.server_ca_file,
ssl_ciphers=t.server_ciphers,
applua=self.read_applua(),
cleanup=self.TNT_CLEANUP,
)

tnt.start()
try:
conn = await asynctnt.connect(host=tnt.host, port=tnt.port,
transport=t.client_transport,
ssl_key_file=t.client_key_file,
ssl_cert_file=t.client_cert_file,
ssl_ca_file=t.client_ca_file,
ssl_ciphers=t.client_ciphers,
reconnect_timeout=0)

tupl = [1, 'hello', 1, 4, 'what is up']
await conn.insert(self.TESTER_SPACE_ID, tupl)
res = await conn.select(self.TESTER_SPACE_NAME, tupl[0:1])
self.assertResponseEqual(res[0], tupl, 'Tuple ok')
except SSLError as e:
if not t.expectSSLError:
self.fail(e)
except asyncio.exceptions.TimeoutError as e:
if not t.expectTimeoutError:
self.fail(e)
except Exception as e:
self.fail(e)
finally:
tnt.stop()

0 comments on commit 205bb67

Please sign in to comment.