Skip to content

Commit c416807

Browse files
fix: Add warning on SSL fallback and improve TLS tests
Changes: - Log warning when SSL connection fails and falls back to non-SSL - Explicitly pass use_tls=False in fallback (clearer intent) - Split test_secure_connection into: - test_explicit_ssl_connection: verifies use_tls=True requires SSL - test_ssl_auto_detect: verifies auto-detect behavior with fallback The new tests are more robust: - test_explicit_ssl_connection fails if SSL isn't working - test_ssl_auto_detect passes whether SSL works or falls back, but verifies warning is logged on fallback Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 618097d commit c416807

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

src/datajoint/connection.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,22 @@ def connect(self) -> None:
223223
charset=config["connection.charset"],
224224
use_tls=self.conn_info.get("ssl"),
225225
)
226-
except Exception:
226+
except Exception as ssl_error:
227227
# If SSL fails, retry without SSL (if it was auto-detected)
228228
if self.conn_info.get("ssl_input") is None:
229+
logger.warning(
230+
"SSL connection failed (%s). Falling back to non-SSL connection. "
231+
"To require SSL, set use_tls=True explicitly.",
232+
ssl_error,
233+
)
229234
self._conn = self.adapter.connect(
230235
host=self.conn_info["host"],
231236
port=self.conn_info["port"],
232237
user=self.conn_info["user"],
233238
password=self.conn_info["passwd"],
234239
init_command=self.init_fun,
235240
charset=config["connection.charset"],
236-
use_tls=None,
241+
use_tls=False, # Explicitly disable SSL for fallback
237242
)
238243
else:
239244
raise

tests/integration/test_tls.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
1+
import logging
2+
13
import pytest
24
from pymysql.err import OperationalError
35

46
import datajoint as dj
57

68

7-
@pytest.mark.xfail(reason="SSL auto-detection needs investigation - may be MySQL container config issue")
8-
def test_secure_connection(db_creds_test, connection_test):
9-
result = dj.conn(reset=True, **db_creds_test).query("SHOW STATUS LIKE 'Ssl_cipher';").fetchone()[1]
10-
assert len(result) > 0
9+
def test_explicit_ssl_connection(db_creds_test, connection_test):
10+
"""When use_tls=True is specified, SSL must be active."""
11+
result = dj.conn(use_tls=True, reset=True, **db_creds_test).query("SHOW STATUS LIKE 'Ssl_cipher';").fetchone()[1]
12+
assert len(result) > 0, "SSL should be active when use_tls=True"
13+
14+
15+
def test_ssl_auto_detect(db_creds_test, connection_test, caplog):
16+
"""When use_tls is not specified, SSL is preferred but fallback is allowed with warning."""
17+
with caplog.at_level(logging.WARNING):
18+
conn = dj.conn(reset=True, **db_creds_test)
19+
result = conn.query("SHOW STATUS LIKE 'Ssl_cipher';").fetchone()[1]
20+
21+
if len(result) > 0:
22+
# SSL connected successfully
23+
assert "SSL connection failed" not in caplog.text
24+
else:
25+
# SSL failed and fell back - warning should be logged
26+
assert "SSL connection failed" in caplog.text
27+
assert "Falling back to non-SSL" in caplog.text
1128

1229

1330
def test_insecure_connection(db_creds_test, connection_test):
31+
"""When use_tls=False, SSL should not be used."""
1432
result = dj.conn(use_tls=False, reset=True, **db_creds_test).query("SHOW STATUS LIKE 'Ssl_cipher';").fetchone()[1]
1533
assert result == ""
1634

1735

1836
def test_reject_insecure(db_creds_test, connection_test):
37+
"""Users with REQUIRE SSL cannot connect without SSL."""
1938
with pytest.raises(OperationalError):
2039
dj.conn(
2140
db_creds_test["host"],

0 commit comments

Comments
 (0)