Skip to content

Adding tests for SSL config options #256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions certgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,28 +122,49 @@ func main() {
anHourAgo := now.Add(time.Hour * -1)

// trustedRoot
// Trusted by drivers. trustedRoot.pem should be installed on driver Docker image among trusted
// Trusted by drivers. trustedRoot.pem should be installed in driver Docker image among trusted
// root CAs.
trustedRootCert, trustedRootKey, trustedRootDer := generateRoot(anHourAgo, tenYearsFromNow, "trustedRoot")
writeKey(path.Join(basePath, "trustedRoot.key"), trustedRootKey)
// customRoot + customRoot2
// Not trusted by the drivers by default. customRoot.crt should be installed in driver Docker image
// in some place. Testkit will only refer to it with its name (no path). It will be used to test custom CA driver settings.
customRootCert, customRootKey, customRootDer := generateRoot(anHourAgo, tenYearsFromNow, "customRoot")
writeKey(path.Join(basePath, "customRoot.key"), customRootKey)
customRoot2Cert, customRoot2Key, customRoot2Der := generateRoot(anHourAgo, tenYearsFromNow, "customRoot2")
writeKey(path.Join(basePath, "customRoot2.key"), customRoot2Key)
// CRT files contains multiple certificates, as long as we only have one trusted in the driver it's
// fine to just write it as this.
// The name ca-certificates.crt assumes that driver Docker images are based on Debian and path
// should be mounted as /etc/ssl/certs/
writeCert(path.Join(basePath, "driver", "trustedRoot.crt"), trustedRootDer)
writeCert(path.Join(basePath, "driver", "trusted", "trustedRoot.crt"), trustedRootDer)
writeCert(path.Join(basePath, "driver", "custom", "customRoot.crt"), customRootDer)
writeCert(path.Join(basePath, "driver", "custom", "customRoot2.crt"), customRoot2Der)

// trustedRoot_server1
// Valid dates with hostname set to something that drivers can connect to from driver
// Docker container.
// Valid dates with hostname set to something that drivers can connect to from driver Docker container.
trustedRoot_server1Key, trustedRoot_server1Der := generateServer(trustedRootCert, trustedRootKey, anHourAgo, tenYearsFromNow, "trustedRoot_thehost", "thehost")
writeKey(path.Join(basePath, "server", "trustedRoot_thehost.key"), trustedRoot_server1Key)
writeCert(path.Join(basePath, "server", "trustedRoot_thehost.pem"), trustedRoot_server1Der)
// customRoot_server1
// now repeat the whole thing for the custom CAs
customRoot_server1Key, customRoot_server1Der := generateServer(customRootCert, customRootKey, anHourAgo, tenYearsFromNow, "customRoot_thehost", "thehost")
writeKey(path.Join(basePath, "server", "customRoot_thehost.key"), customRoot_server1Key)
writeCert(path.Join(basePath, "server", "customRoot_thehost.pem"), customRoot_server1Der)
customRoot2_server1Key, customRoot2_server1Der := generateServer(customRoot2Cert, customRoot2Key, anHourAgo, tenYearsFromNow, "customRoot2_thehost", "thehost")
writeKey(path.Join(basePath, "server", "customRoot2_thehost.key"), customRoot2_server1Key)
writeCert(path.Join(basePath, "server", "customRoot2_thehost.pem"), customRoot2_server1Der)

// trustedRoot_server2
// Expired dates, otherwise same as server1.
trustedRoot_server2Key, trustedRoot_server2Der := generateServer(trustedRootCert, trustedRootKey, tenYearsAgo, anHourAgo, "trustedRoot_thehost", "thehost")
writeKey(path.Join(basePath, "server", "trustedRoot_thehost_expired.key"), trustedRoot_server2Key)
writeCert(path.Join(basePath, "server", "trustedRoot_thehost_expired.pem"), trustedRoot_server2Der)
// customRoot_server2
// now repeat the whole thing for the custom CA
customRoot_server2Key, customRoot_server2Der := generateServer(customRootCert, customRootKey, tenYearsAgo, anHourAgo, "customRoot_thehost", "thehost")
writeKey(path.Join(basePath, "server", "customRoot_thehost_expired.key"), customRoot_server2Key)
writeCert(path.Join(basePath, "server", "customRoot_thehost_expired.pem"), customRoot_server2Der)

// untrustedRoot
// Not trusted by drivers otherwise same as trustedRoot.
Expand Down
7 changes: 6 additions & 1 deletion driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ def _ensure_image(testkit_path, docker_image_path, branch_name, driver_name,
cas_path = os.path.join(docker_image_path, "CAs")
shutil.rmtree(cas_path, ignore_errors=True)
cas_source_path = os.path.join(testkit_path, "tests", "tls",
"certs", "driver")
"certs", "driver", "trusted")
shutil.copytree(cas_source_path, cas_path)
custom_cas_path = os.path.join(docker_image_path, "CustomCAs")
shutil.rmtree(custom_cas_path, ignore_errors=True)
custom_cas_source_path = os.path.join(testkit_path, "tests", "tls",
"certs", "driver", "custom")
shutil.copytree(custom_cas_source_path, custom_cas_path)

# This will use the driver folder as build context.
docker.build_and_tag(image_name, docker_image_path,
Expand Down
6 changes: 4 additions & 2 deletions nutkit/frontend/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ class Driver:
def __init__(self, backend, uri, auth_token, user_agent=None,
resolver_fn=None, domain_name_resolver_fn=None,
connection_timeout_ms=None, fetch_size=None,
max_tx_retry_time_ms=None):
max_tx_retry_time_ms=None, encrypted=None,
trusted_certificates=None):
self._backend = backend
self._resolver_fn = resolver_fn
self._domain_name_resolver_fn = domain_name_resolver_fn
Expand All @@ -15,7 +16,8 @@ def __init__(self, backend, uri, auth_token, user_agent=None,
resolverRegistered=resolver_fn is not None,
domainNameResolverRegistered=domain_name_resolver_fn is not None,
connectionTimeoutMs=connection_timeout_ms,
fetchSize=fetch_size, maxTxRetryTimeMs=max_tx_retry_time_ms)
fetchSize=fetch_size, maxTxRetryTimeMs=max_tx_retry_time_ms,
encrypted=encrypted, trustedCertificates=trusted_certificates)
res = backend.send_and_receive(req)
if not isinstance(res, protocol.Driver):
raise Exception("Should be Driver but was %s" % res)
Expand Down
9 changes: 9 additions & 0 deletions nutkit/protocol/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ class Feature(Enum):
# This methods asserts that exactly one record in left in the result
# stream, else it will raise an exception.
API_RESULT_SINGLE = "Feature:API:Result.Single"
# The driver implements explicit configuration options for SSL.
# - enable / disable SSL
# - verify signature against system store / custom cert / not at all
API_SSL_CONFIG = "Feature:API:SSLConfig"
# The driver understands bolt+s, bolt+ssc, neo4j+s, and neo4j+ssc schemes
# and will configure its ssl options automatically.
# ...+s: enforce SSL + verify server's signature with system's trust store
# ...+ssc: enforce SSL but do not verify the server's signature at all
API_SSL_SCHEMES = "Feature:API:SSLSchemes"
# The driver supports single-sign-on (SSO) by providing a bearer auth token
# API.
AUTH_BEARER = "Feature:Auth:Bearer"
Expand Down
16 changes: 15 additions & 1 deletion nutkit/protocol/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ class NewDriver:
def __init__(
self, uri, authToken, userAgent=None, resolverRegistered=False,
domainNameResolverRegistered=False, connectionTimeoutMs=None,
fetchSize=None, maxTxRetryTimeMs=None
fetchSize=None, maxTxRetryTimeMs=None, encrypted=None,
trustedCertificates=None
):
# Neo4j URI to connect to
self.uri = uri
Expand All @@ -70,6 +71,19 @@ def __init__(
assert hasattr(Feature, "TMP_DRIVER_MAX_TX_RETRY_TIME")
if maxTxRetryTimeMs is not None:
self.maxTxRetryTimeMs = maxTxRetryTimeMs
# (bool) whether to enable or disable encryption
# field missing in message: use driver default (should be False)
if encrypted is not None:
self.encrypted = encrypted
# None: trust system CAs
# [] (empty list): trust any certificate
# ["path", ...] (list of strings): custom CA certificates to trust
# field missing in message: use driver default (should be system CAs)
if trustedCertificates is not None:
if trustedCertificates == "None":
self.trustedCertificates = None
else:
self.trustedCertificates = trustedCertificates


class AuthorizationToken:
Expand Down
5 changes: 5 additions & 0 deletions tests/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ def get_driver_features(backend):
protocol.Feature.BOLT_4_3,
protocol.Feature.BOLT_4_4,
))
# TODO: remove this block once all drivers list this feature
# they all support the functionality already
if get_driver_name() in ["python", "java", "go", "dotnet"]:
assert protocol.Feature.API_SSL_SCHEMES not in features
features.add(protocol.Feature.API_SSL_SCHEMES)
print("features", features)
return features
except (OSError, protocol.BaseError) as e:
Expand Down
5 changes: 5 additions & 0 deletions tests/tls/certs/customRoot.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIB2DavQnjDSvTFbcQ8LAiOf0jdJw2vE5ws8BXimCubHOoAoGCCqGSM49
AwEHoUQDQgAE7iYj3U966MS9xqfqn9hbG11Fe6+5rExRZNO3qqnosyFRMqaZ7U54
hPwjVsqHOsvhMI7M71BXqrd6iOhkHsbFIA==
-----END EC PRIVATE KEY-----
5 changes: 5 additions & 0 deletions tests/tls/certs/customRoot2.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIDK5fELEd3XFyNDsHpV32VcNtBmXWejBXDO/0wLIueHGoAoGCCqGSM49
AwEHoUQDQgAEKtc4mzv0JEBevEtp6hDadUMTGhtl78i38IJXABB3fDUjeGdQQynB
7YaHtPFbxPOmR2VfgRybMhDhwMQxZcTsAw==
-----END EC PRIVATE KEY-----
11 changes: 11 additions & 0 deletions tests/tls/certs/driver/custom/customRoot.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBfzCCASWgAwIBAgIQG6ywjQkkfBgCXAM3e21cMTAKBggqhkjOPQQDAjAVMRMw
EQYDVQQDEwpjdXN0b21Sb290MB4XDTIxMDkyNzExNDY1MFoXDTQxMDkyMjEyNDY1
MFowFTETMBEGA1UEAxMKY3VzdG9tUm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEH
A0IABO4mI91PeujEvcan6p/YWxtdRXuvuaxMUWTTt6qp6LMhUTKmme1OeIT8I1bK
hzrL4TCOzO9QV6q3eojoZB7GxSCjVzBVMA4GA1UdDwEB/wQEAwICBDATBgNVHSUE
DDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRGg7urqkqX
cidUaYZ7IhcpqW41lTAKBggqhkjOPQQDAgNIADBFAiBeFBloeaSr9fa6N94GmeaE
3qOrcRS4dqWf5A81OwmFegIhAOs9fcjfeHBmX2r07WN07RlbYXag4xlnl1BQUbAj
UMXk
-----END CERTIFICATE-----
11 changes: 11 additions & 0 deletions tests/tls/certs/driver/custom/customRoot2.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBgDCCASegAwIBAgIQBFCs0ckOUAPEmdkVdEOa8DAKBggqhkjOPQQDAjAWMRQw
EgYDVQQDEwtjdXN0b21Sb290MjAeFw0yMTA5MjcxMTQ2NTBaFw00MTA5MjIxMjQ2
NTBaMBYxFDASBgNVBAMTC2N1c3RvbVJvb3QyMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEKtc4mzv0JEBevEtp6hDadUMTGhtl78i38IJXABB3fDUjeGdQQynB7YaH
tPFbxPOmR2VfgRybMhDhwMQxZcTsA6NXMFUwDgYDVR0PAQH/BAQDAgIEMBMGA1Ud
JQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNDV2FCL
wDKV0dSdrhodOt+U0kmAMAoGCCqGSM49BAMCA0cAMEQCIAeUEL4P4gsY0gmOQ2i+
/eXJvLH7iOxMmIW7RugnOc1ZAiACq1JA0BYyMZzDWl/8cn1Qs/0R35t/te+G5+K0
VsqVbg==
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions tests/tls/certs/server/customRoot2_thehost.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICzYDTUBiNlCIngyqiTQ86fkG5KAvPPIAXbUW7kcMD9YoAoGCCqGSM49
AwEHoUQDQgAESiRDcNXhPOKcT0HSLhNcVQsICPHYMgJcpz/nzhYWVAs5SGFyQM5i
vitjDQob2TkY5N8SUPVg3BzfNu08ny5mtw==
-----END EC PRIVATE KEY-----
10 changes: 10 additions & 0 deletions tests/tls/certs/server/customRoot2_thehost.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBezCCASGgAwIBAgIQauOWHc5x54LVpRIRRzAPKTAKBggqhkjOPQQDAjAWMRQw
EgYDVQQDEwtjdXN0b21Sb290MjAeFw0yMTA5MjcxMTQ2NTBaFw00MTA5MjIxMjQ2
NTBaMB4xHDAaBgNVBAMME2N1c3RvbVJvb3QyX3RoZWhvc3QwWTATBgcqhkjOPQIB
BggqhkjOPQMBBwNCAARKJENw1eE84pxPQdIuE1xVCwgI8dgyAlynP+fOFhZUCzlI
YXJAzmK+K2MNChvZORjk3xJQ9WDcHN827TyfLma3o0kwRzAOBgNVHQ8BAf8EBAMC
BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADASBgNVHREECzAJ
ggd0aGVob3N0MAoGCCqGSM49BAMCA0gAMEUCIQDOh74w1gEy/CrjGmxfMPkrFIWz
I+bG9Ck28akdACUC0QIgRnidQd3BRR10bIaws7/QFB/s0070Ok+OJhYrvhZN55Q=
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions tests/tls/certs/server/customRoot_thehost.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMF+VyuuzaUjcum67tkMJnpcQWR8B/wnkNW1tkKSYUCroAoGCCqGSM49
AwEHoUQDQgAEPbA6GMdGy7sIXMoAKbaNEdJZa0yGrOtS04UOuodCfIKPh099YT9t
D+kJ0sJtgiWvz75CJXvBE1ZVXG5DX8XssQ==
-----END EC PRIVATE KEY-----
10 changes: 10 additions & 0 deletions tests/tls/certs/server/customRoot_thehost.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBezCCASCgAwIBAgIRAPW09/lYACnO/SApHmOa+GEwCgYIKoZIzj0EAwIwFTET
MBEGA1UEAxMKY3VzdG9tUm9vdDAeFw0yMTA5MjcxMTQ2NTBaFw00MTA5MjIxMjQ2
NTBaMB0xGzAZBgNVBAMMEmN1c3RvbVJvb3RfdGhlaG9zdDBZMBMGByqGSM49AgEG
CCqGSM49AwEHA0IABD2wOhjHRsu7CFzKACm2jRHSWWtMhqzrUtOFDrqHQnyCj4dP
fWE/bQ/pCdLCbYIlr8++QiV7wRNWVVxuQ1/F7LGjSTBHMA4GA1UdDwEB/wQEAwIF
oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBIGA1UdEQQLMAmC
B3RoZWhvc3QwCgYIKoZIzj0EAwIDSQAwRgIhAJqA5gax2RvjhcwXkMBvoBSwTTfl
huKrHFgTkf60swI7AiEA5fYtkckwZFk+6D/fUBIjc0UZgHF0KLKM0zcFWtuYyr8=
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions tests/tls/certs/server/customRoot_thehost_expired.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIDm3744x0TZfnfTNQaxaN98clgGPS9iy7Blj6XGWTEDAoAoGCCqGSM49
AwEHoUQDQgAEsYrhTVlHdnS6l8OtfK46y/hXW/3M6QX1DjPx/4epOXbAXk9XkmcI
phz6MV9p8YteCbDgKtAy4QuHv/dyHsLKVw==
-----END EC PRIVATE KEY-----
10 changes: 10 additions & 0 deletions tests/tls/certs/server/customRoot_thehost_expired.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBeDCCAR+gAwIBAgIQfYQ2BYaQwMOUjvubE4a8ZTAKBggqhkjOPQQDAjAVMRMw
EQYDVQQDEwpjdXN0b21Sb290MB4XDTAxMTAwMjEyNDY1MFoXDTIxMDkyNzExNDY1
MFowHTEbMBkGA1UEAwwSY3VzdG9tUm9vdF90aGVob3N0MFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEsYrhTVlHdnS6l8OtfK46y/hXW/3M6QX1DjPx/4epOXbAXk9X
kmcIphz6MV9p8YteCbDgKtAy4QuHv/dyHsLKV6NJMEcwDgYDVR0PAQH/BAQDAgWg
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwEgYDVR0RBAswCYIH
dGhlaG9zdDAKBggqhkjOPQQDAgNHADBEAiAEcKjBFoE1iYrdmoJ7WDndMEXyvmK+
wBGbvdlapzEUlAIgGm0uf3OPPdg3O9bP95T1DSjwqy5208+IjRwO2MJwabc=
-----END CERTIFICATE-----
6 changes: 3 additions & 3 deletions tests/tls/certs/trustedRoot.key
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOoIWnYkga2JY0QUbauE5+4IYKnxrS2XxF83lyeA+2VkoAoGCCqGSM49
AwEHoUQDQgAEjyaeSLCcHcEHz72b4w/q3k8l9VHe015DvwZ/7/B0nTtafwWvvL9D
qq/OJ6hgIYQpFyhZcLcFqQ8FLCzeH8GbRw==
MHcCAQEEIAvxrkdyTpeA1vWaCJxlQOZZsq6t2nu477SX/K0/o/RwoAoGCCqGSM49
AwEHoUQDQgAE74l9pA6YhikKz49gjmlTnS0IdT/O3mh4eODQYDlzYCsjdgRCIKtj
Tej/SW9wFPyi5v52F5y7uLGrONDxR3U1Zg==
-----END EC PRIVATE KEY-----
82 changes: 0 additions & 82 deletions tests/tls/securescheme.py

This file was deleted.

Loading