Skip to content

Commit 105cefb

Browse files
committed
Secure by default
1 parent 9522843 commit 105cefb

File tree

4 files changed

+27
-11
lines changed

4 files changed

+27
-11
lines changed

neo4j/__init__.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,9 @@ class DirectDriver(Driver):
191191

192192
def __new__(cls, uri, **config):
193193
from neobolt.addressing import SocketAddress
194-
from neobolt.direct import DirectConnectionPool, DEFAULT_PORT, connect
195-
from neobolt.security import SecurityPlan
194+
from neobolt.compat.ssl import SSL_AVAILABLE
195+
from neobolt.direct import ConnectionPool, DEFAULT_PORT, connect
196+
from neobolt.security import ENCRYPTION_OFF, ENCRYPTION_ON, SecurityPlan
196197
cls._check_uri(uri)
197198
if SocketAddress.parse_routing_context(uri):
198199
raise ValueError("Parameters are not supported with scheme 'bolt'. Given URI: '%s'." % uri)
@@ -203,13 +204,15 @@ def __new__(cls, uri, **config):
203204
# the connection pool may contain multiple IP address keys, one for
204205
# an old address and one for a new address.
205206
instance.address = SocketAddress.from_uri(uri, DEFAULT_PORT)
207+
if config.get("encrypted") is None:
208+
config["encrypted"] = ENCRYPTION_ON if SSL_AVAILABLE else ENCRYPTION_OFF
206209
instance.security_plan = security_plan = SecurityPlan.build(**config)
207210
instance.encrypted = security_plan.encrypted
208211

209-
def connector(address, error_handler):
210-
return connect(address, security_plan.ssl_context, error_handler, **config)
212+
def connector(address, **kwargs):
213+
return connect(address, **dict(config, **kwargs))
211214

212-
pool = DirectConnectionPool(connector, instance.address, **config)
215+
pool = ConnectionPool(connector, instance.address, **config)
213216
pool.release(pool.acquire())
214217
instance._pool = pool
215218
instance._max_retry_time = config.get("max_retry_time", default_config["max_retry_time"])
@@ -231,12 +234,15 @@ class RoutingDriver(Driver):
231234

232235
def __new__(cls, uri, **config):
233236
from neobolt.addressing import SocketAddress
237+
from neobolt.compat.ssl import SSL_AVAILABLE
234238
from neobolt.direct import DEFAULT_PORT, connect
235239
from neobolt.routing import RoutingConnectionPool
236-
from neobolt.security import SecurityPlan
240+
from neobolt.security import ENCRYPTION_OFF, ENCRYPTION_ON, SecurityPlan
237241
cls._check_uri(uri)
238242
instance = object.__new__(cls)
239243
instance.initial_address = initial_address = SocketAddress.from_uri(uri, DEFAULT_PORT)
244+
if config.get("encrypted") is None:
245+
config["encrypted"] = ENCRYPTION_ON if SSL_AVAILABLE else ENCRYPTION_OFF
240246
instance.security_plan = security_plan = SecurityPlan.build(**config)
241247
instance.encrypted = security_plan.encrypted
242248
routing_context = SocketAddress.parse_routing_context(uri)
@@ -245,8 +251,8 @@ def __new__(cls, uri, **config):
245251
# scenario right now
246252
raise ValueError("TRUST_ON_FIRST_USE is not compatible with routing")
247253

248-
def connector(address, error_handler):
249-
return connect(address, security_plan.ssl_context, error_handler, **config)
254+
def connector(address, **kwargs):
255+
return connect(address, **dict(config, **kwargs))
250256

251257
pool = RoutingConnectionPool(connector, initial_address, routing_context, initial_address, **config)
252258
try:
@@ -1003,6 +1009,8 @@ def __init__(self, **metadata):
10031009
self.counters = SummaryCounters(metadata.get("stats", {}))
10041010
self.result_available_after = metadata.get("result_available_after")
10051011
self.result_consumed_after = metadata.get("result_consumed_after")
1012+
self.t_first = metadata.get("t_first")
1013+
self.t_last = metadata.get("t_last")
10061014
if "plan" in metadata:
10071015
self.plan = _make_plan(metadata["plan"])
10081016
if "profile" in metadata:

test/integration/test_security.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929

3030
class SecurityTestCase(IntegrationTestCase):
3131

32+
def test_secure_by_default(self):
33+
with GraphDatabase.driver(self.bolt_uri, auth=self.auth_token) as driver:
34+
self.assertTrue(driver.encrypted)
35+
3236
def test_insecure_session_uses_normal_socket(self):
3337
with GraphDatabase.driver(self.bolt_uri, auth=self.auth_token, encrypted=False) as driver:
3438
with driver.session() as session:

test/integration/test_session.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,12 @@ def test_contains_time_information(self):
232232
raise SkipTest("Execution times are not supported before server 3.1")
233233
with self.driver.session() as session:
234234
summary = session.run("UNWIND range(1,1000) AS n RETURN n AS number").consume()
235-
assert isinstance(summary.result_consumed_after, int)
236-
assert isinstance(summary.result_available_after, int)
235+
if self.protocol_version() >= 3:
236+
self.assertIsInstance(summary.t_first, int)
237+
self.assertIsInstance(summary.t_last, int)
238+
else:
239+
self.assertIsInstance(summary.result_available_after, int)
240+
self.assertIsInstance(summary.result_consumed_after, int)
237241

238242

239243
class ResetTestCase(DirectIntegrationTestCase):

test/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
boltkit
1+
boltkit>=1.0.34
22
coverage
33
mock
44
pytest

0 commit comments

Comments
 (0)