Skip to content

connection: preserve explicit empty ssl_options#938

Draft
dkropachev wants to merge 1 commit into
masterfrom
fix-empty-ssl-options-reactors
Draft

connection: preserve explicit empty ssl_options#938
dkropachev wants to merge 1 commit into
masterfrom
fix-empty-ssl-options-reactors

Conversation

@dkropachev

Copy link
Copy Markdown
Collaborator

Summary

Problem: several SSL paths used ssl_options truthiness, so explicit ssl_options={} was treated like omitted ssl_options=None. That could disable SSL setup in connection/reactor paths, skip the legacy deprecation warning, and make Insights report SSL as disabled.

Fix: preserve whether ssl_options was supplied and use that state for SSL-enabled checks. Explicit ssl_options={} now enables SSL with default options; omitted ssl_options=None remains disabled. Twisted/Eventlet build pyOpenSSL contexts for legacy options, while the standard path builds an SSLContext.

Closes #937.

Driver Surface

Touches connection initialization, asyncio/Eventlet/Twisted SSL setup, client-routes SSL mode, and Insights startup reporting. Public Cluster API and protocol format are unchanged.

Compatibility and Protocol Risk

No protocol changes. The behavior change is limited to callers that explicitly pass ssl_options={} or endpoint SSL options: those are now treated as SSL-enabled instead of plaintext.

Tests

  • uv run pytest -rf tests/unit/test_connection.py tests/unit/test_client_routes.py tests/unit/advanced/test_insights.py tests/unit/io/test_twistedreactor.py tests/unit/io/test_eventletreactor.py tests/unit/io/test_asyncioreactor.py
  • Attempted uv run pytest -rf tests/unit; it fails in tests/unit/test_types.py::DateRangeDeserializationTests::test_deserialize_date_range_year, reproduced in isolation and unrelated to this change.

Integration scenario to consider: connect to a TLS cluster with Cluster(..., ssl_options={}) under the default, Twisted, and Eventlet reactors.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2256048f-5ce4-47ac-821b-6fef3fb8957a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change distinguishes omitted SSL options from explicitly supplied options, including {}, across connection initialization, asyncio, Eventlet, and Twisted reactors. It adds shared pyOpenSSL certificate and hostname validation, updates Insights reporting and shard-aware SSL routing, adjusts cloud TLS method selection and cluster validation, and adds focused tests.

Sequence Diagram(s)

sequenceDiagram
  participant Cluster
  participant Connection
  participant Reactor
  participant pyOpenSSL
  Cluster->>Connection: provide ssl_options or ssl_context
  Connection->>Reactor: expose normalized SSL state
  Reactor->>pyOpenSSL: build context and perform handshake
  pyOpenSSL-->>Reactor: provide peer certificate
  Reactor->>Connection: validate certificate hostname
Loading

Possibly related PRs

Suggested labels: area/Driver_-_python-driver

Suggested reviewers: lorak-mmk

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Cloud TLS method-selection changes and their tests are outside #937’s SSL-options truthiness scope. Either remove the cloud/OpenSSL method-selection work or split it into a separate PR with its own linked issue and justification.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: preserving explicit empty ssl_options handling.
Description check ✅ Passed The PR description covers the summary, impact, compatibility, and tests, and matches the repository checklist well.
Linked Issues check ✅ Passed The changes align with #937 by treating ssl_context/ssl_options as explicit predicates across connection, reactors, and Insights, with focused tests.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dkropachev
dkropachev force-pushed the fix-empty-ssl-options-reactors branch from 704dde9 to 805b678 Compare July 20, 2026 19:15
@coderabbitai
coderabbitai Bot requested a review from Lorak-mmk July 20, 2026 19:16
Comment thread cassandra/io/twistedreactor.py Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
cassandra/io/eventletreactor.py (1)

121-158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Dead code: uses_legacy_ssl_options is now always False.

Since __init__ hardcodes self.uses_legacy_ssl_options = False and nothing else ever sets it True, the if self.uses_legacy_ssl_options: super()... branches in _initiate_connection and _validate_hostname are now unreachable. TwistedConnection doesn't carry this flag at all and branches on _ssl_enabled directly — consider removing the vestigial flag/branches here for consistency and to avoid implying conditional behavior that no longer exists.

♻️ Suggested cleanup
     def __init__(self, *args, **kwargs):
         Connection.__init__(self, *args, **kwargs)
-        self.uses_legacy_ssl_options = False
         self._write_queue = Queue()
...
     def _initiate_connection(self, sockaddr):
-        if self.uses_legacy_ssl_options:
-            super(EventletConnection, self)._initiate_connection(sockaddr)
-        else:
-            self._socket.connect(sockaddr)
-            if self._ssl_enabled:
-                self._socket.do_handshake()
+        self._socket.connect(sockaddr)
+        if self._ssl_enabled:
+            self._socket.do_handshake()

     def _validate_hostname(self):
-        if self.uses_legacy_ssl_options:
-            super(EventletConnection, self)._validate_hostname()
-        else:
-            expected_name = (self.ssl_options or {}).get('server_hostname') or self.endpoint.address
-            _validate_pyopenssl_hostname(self._socket.get_peer_certificate(), expected_name)
+        expected_name = (self.ssl_options or {}).get('server_hostname') or self.endpoint.address
+        _validate_pyopenssl_hostname(self._socket.get_peer_certificate(), expected_name)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cassandra/io/eventletreactor.py` around lines 121 - 158, Remove the hardcoded
uses_legacy_ssl_options assignment from EventletConnection.__init__ and delete
the unreachable legacy branches in _initiate_connection and _validate_hostname.
Keep the current non-legacy socket connection, handshake, and hostname
validation behavior as the unconditional implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cassandra/io/eventletreactor.py`:
- Around line 121-158: Remove the hardcoded uses_legacy_ssl_options assignment
from EventletConnection.__init__ and delete the unreachable legacy branches in
_initiate_connection and _validate_hostname. Keep the current non-legacy socket
connection, handshake, and hostname validation behavior as the unconditional
implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f288eee-0f6d-48f6-b321-96aa8ca19b32

📥 Commits

Reviewing files that changed from the base of the PR and between bcc2d3d and 805b678.

📒 Files selected for processing (13)
  • cassandra/cluster.py
  • cassandra/connection.py
  • cassandra/datastax/insights/reporter.py
  • cassandra/io/asyncioreactor.py
  • cassandra/io/eventletreactor.py
  • cassandra/io/twistedreactor.py
  • cassandra/pool.py
  • tests/unit/advanced/test_insights.py
  • tests/unit/io/test_eventletreactor.py
  • tests/unit/io/test_twistedreactor.py
  • tests/unit/test_client_routes.py
  • tests/unit/test_connection.py
  • tests/unit/test_shard_aware.py

@dkropachev dkropachev self-assigned this Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
cassandra/datastax/cloud/__init__.py (1)

188-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use raise ... from for cleaner exception chaining.

Within an except clause, using raise ... from e is the idiomatic Python 3 approach. It automatically preserves the original traceback and sets the __cause__ attribute, making it cleaner than manually chaining with .with_traceback().
As per static analysis hints, within an except clause, exceptions should be raised with raise ... from err to distinguish them from errors in exception handling.

♻️ Proposed refactor
     try:
         from OpenSSL import SSL
     except ImportError as e:
         raise ImportError(
-            "PyOpenSSL must be installed to connect to Astra with the Eventlet or Twisted event loops")\
-            .with_traceback(e.__traceback__)
+            "PyOpenSSL must be installed to connect to Astra with the Eventlet or Twisted event loops"
+        ) from e
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cassandra/datastax/cloud/__init__.py` around lines 188 - 193, Update the
OpenSSL import error handling in the cloud initialization code to raise the
custom ImportError using Python’s explicit exception chaining syntax with the
caught exception as its cause. Remove the manual .with_traceback() chaining
while preserving the existing error message and behavior.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cassandra/datastax/cloud/__init__.py`:
- Around line 188-193: Update the OpenSSL import error handling in the cloud
initialization code to raise the custom ImportError using Python’s explicit
exception chaining syntax with the caught exception as its cause. Remove the
manual .with_traceback() chaining while preserving the existing error message
and behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8b73f8af-9ad3-478c-ae6a-58f2804a5f23

📥 Commits

Reviewing files that changed from the base of the PR and between 805b678 and 8e17dd5.

📒 Files selected for processing (7)
  • cassandra/datastax/cloud/__init__.py
  • cassandra/io/eventletreactor.py
  • cassandra/io/twistedreactor.py
  • tests/unit/io/test_eventletreactor.py
  • tests/unit/io/test_twistedreactor.py
  • tests/unit/test_cloud.py
  • tests/unit/test_cluster.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/unit/io/test_twistedreactor.py
  • cassandra/io/eventletreactor.py
  • cassandra/io/twistedreactor.py
  • tests/unit/io/test_eventletreactor.py

@dkropachev
dkropachev force-pushed the fix-empty-ssl-options-reactors branch from 8e17dd5 to f119103 Compare July 20, 2026 22:24
@dkropachev

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
cassandra/io/twistedreactor.py (1)

43-80: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate pyOpenSSL helpers across reactors and cloud module.

_default_ssl_method (43-48) is an exact duplicate of cassandra/datastax/cloud/__init__.py::_default_pyopenssl_ssl_method, and per the codebase graph, cassandra/io/eventletreactor.py defines an identical _default_ssl_method/_build_pyopenssl_context_from_options pair as well. Three independent copies of TLS negotiation/context-building logic increase the risk of divergence (e.g. one path missing a future security fix).

Extracting these into a single shared module (e.g. near _validate_pyopenssl_hostname in cassandra/connection.py) would remove the duplication.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cassandra/io/twistedreactor.py` around lines 43 - 80, Extract the shared
pyOpenSSL TLS negotiation and context-building logic from `_default_ssl_method`
and `_build_pyopenssl_context_from_options` into a common helper module,
alongside the existing shared SSL utilities such as
`_validate_pyopenssl_hostname`. Update `cassandra/io/twistedreactor.py`,
`cassandra/io/eventletreactor.py`, and `cassandra/datastax/cloud/__init__.py` to
import and reuse the shared helpers, preserving their current certificate,
verification, and fallback behavior.
cassandra/datastax/cloud/__init__.py (1)

179-184: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate TLS-method-selection helper across three modules.

This exact loop-and-fallback logic is duplicated verbatim in cassandra/io/twistedreactor.py (_default_ssl_method) and, per the codebase graph, cassandra/io/eventletreactor.py (_default_ssl_method). Three independent copies of security-relevant TLS negotiation logic risk silently diverging if one is patched without the others.

Consider hoisting this into a single shared helper (e.g. alongside _validate_pyopenssl_hostname in cassandra/connection.py) and having all three call sites import it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cassandra/datastax/cloud/__init__.py` around lines 179 - 184, Consolidate the
duplicated TLS method-selection loop from _default_pyopenssl_ssl_method,
twistedreactor._default_ssl_method, and eventletreactor._default_ssl_method into
one shared helper alongside _validate_pyopenssl_hostname in connection.py.
Update all three modules to import and call the shared helper, removing their
local implementations while preserving the existing method order and ImportError
fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unit/io/test_eventletreactor.py`:
- Around line 122-131: Update test_validate_hostname_rejects_mismatch and
test_validate_hostname_prefers_san_over_common_name to assert
ssl.CertificateError specifically when _validate_hostname rejects the
certificate, replacing the broad Exception assertion while preserving the
existing test setup and invocation.

---

Nitpick comments:
In `@cassandra/datastax/cloud/__init__.py`:
- Around line 179-184: Consolidate the duplicated TLS method-selection loop from
_default_pyopenssl_ssl_method, twistedreactor._default_ssl_method, and
eventletreactor._default_ssl_method into one shared helper alongside
_validate_pyopenssl_hostname in connection.py. Update all three modules to
import and call the shared helper, removing their local implementations while
preserving the existing method order and ImportError fallback.

In `@cassandra/io/twistedreactor.py`:
- Around line 43-80: Extract the shared pyOpenSSL TLS negotiation and
context-building logic from `_default_ssl_method` and
`_build_pyopenssl_context_from_options` into a common helper module, alongside
the existing shared SSL utilities such as `_validate_pyopenssl_hostname`. Update
`cassandra/io/twistedreactor.py`, `cassandra/io/eventletreactor.py`, and
`cassandra/datastax/cloud/__init__.py` to import and reuse the shared helpers,
preserving their current certificate, verification, and fallback behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e9c06e84-df9d-4864-bb9c-2a2a66a988d5

📥 Commits

Reviewing files that changed from the base of the PR and between 8e17dd5 and f119103.

📒 Files selected for processing (16)
  • cassandra/cluster.py
  • cassandra/connection.py
  • cassandra/datastax/cloud/__init__.py
  • cassandra/datastax/insights/reporter.py
  • cassandra/io/asyncioreactor.py
  • cassandra/io/eventletreactor.py
  • cassandra/io/twistedreactor.py
  • cassandra/pool.py
  • tests/unit/advanced/test_insights.py
  • tests/unit/io/test_eventletreactor.py
  • tests/unit/io/test_twistedreactor.py
  • tests/unit/test_client_routes.py
  • tests/unit/test_cloud.py
  • tests/unit/test_cluster.py
  • tests/unit/test_connection.py
  • tests/unit/test_shard_aware.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • tests/unit/test_cloud.py
  • tests/unit/test_cluster.py
  • tests/unit/test_client_routes.py
  • cassandra/cluster.py
  • tests/unit/io/test_twistedreactor.py
  • cassandra/pool.py
  • tests/unit/advanced/test_insights.py
  • cassandra/io/eventletreactor.py
  • cassandra/connection.py

Comment thread tests/unit/io/test_eventletreactor.py Outdated
@dkropachev

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
coderabbitai Bot requested a review from Lorak-mmk July 21, 2026 15:09
Copilot AI review requested due to automatic review settings July 21, 2026 20:10
Comment thread tests/unit/io/test_eventletreactor.py Fixed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Normalizes explicit empty ssl_options handling so {} enables TLS while None remains disabled.

Changes:

  • Preserves explicit SSL configuration across connections, reactors, routing, and Insights.
  • Builds default SSL contexts for standard, Eventlet, and Twisted paths.
  • Adds focused SSL behavior and compatibility tests.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
cassandra/connection.py Preserves explicit SSL state and builds contexts.
cassandra/cluster.py Corrects cloud validation and warnings.
cassandra/pool.py Updates shard-aware TLS port selection.
cassandra/io/asyncioreactor.py Uses normalized SSL state.
cassandra/io/eventletreactor.py Builds pyOpenSSL contexts for Eventlet.
cassandra/io/twistedreactor.py Builds pyOpenSSL contexts for Twisted.
cassandra/datastax/cloud/__init__.py Selects modern pyOpenSSL methods.
cassandra/datastax/insights/reporter.py Corrects SSL startup reporting.
tests/unit/test_connection.py Tests connection SSL semantics.
tests/unit/test_cluster.py Tests cloud conflicts and warnings.
tests/unit/test_cloud.py Tests pyOpenSSL method fallback.
tests/unit/test_client_routes.py Tests empty options with TLS routes.
tests/unit/test_shard_aware.py Tests shard-aware SSL ports.
tests/unit/io/test_eventletreactor.py Tests Eventlet SSL contexts.
tests/unit/io/test_twistedreactor.py Tests Twisted SSL contexts.
tests/unit/advanced/test_insights.py Tests Insights SSL reporting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cassandra/pool.py
Comment thread cassandra/io/eventletreactor.py Outdated
Comment thread cassandra/io/eventletreactor.py Outdated
Comment thread cassandra/io/eventletreactor.py Outdated
Copilot AI review requested due to automatic review settings July 21, 2026 21:52
@dkropachev
dkropachev force-pushed the fix-empty-ssl-options-reactors branch from f8c3ca4 to 9bcedb1 Compare July 21, 2026 21:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Comment thread cassandra/io/eventletreactor.py Outdated
Comment thread cassandra/datastax/insights/reporter.py Outdated
Comment thread tests/unit/io/test_twistedreactor.py Outdated
Comment thread tests/unit/io/test_eventletreactor.py Outdated
@dkropachev
dkropachev force-pushed the fix-empty-ssl-options-reactors branch from 9bcedb1 to d77f7f0 Compare July 22, 2026 00:51
Copilot AI review requested due to automatic review settings July 22, 2026 03:34
@dkropachev

Copy link
Copy Markdown
Collaborator Author

Addressed review feedback in a2e58d48d:

  • Removed unreachable Eventlet legacy SSL branches and added shared pyOpenSSL hostname validation for Eventlet/Twisted.
  • Reused shared pyOpenSSL TLS helpers for stdlib protocol, cert_reqs, and ciphers handling; updated cloud ImportError chaining to raise ... from.
  • Preserved endpoint-only SSL handling for shard-aware ports and Insights startup reporting.
  • Updated fallback assertions to call _default_ssl_method().

Validation:

  • uv run pytest -rf tests/unit/io/test_eventletreactor.py tests/unit/io/test_twistedreactor.py tests/unit/advanced/test_insights.py tests/unit/test_shard_aware.py tests/unit/test_cloud.py
  • uv run pytest -rf tests/unit/test_connection.py

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

cassandra/datastax/insights/reporter.py:180

  • Connection.__init__ always creates an instance ssl_options dict, using {} even when the option was omitted. Preferring any non-None connection value here therefore makes every real plaintext control connection report enabled: true (and certValidation: false). The omitted-options test misses this because its mock leaves the attribute unset. Use _ssl_options_explicit (while retaining non-empty options for compatibility) before selecting the connection-level dict.
        ssl_options = (connection_ssl_options
                       if connection_ssl_options is not None
                       else self._session.cluster.ssl_options)
        ssl_options_explicit = bool(_safe_getattr(connection, '_ssl_options_explicit', False))
        ssl_enabled = (ssl_context is not None or
                       ssl_options is not None or
                       endpoint_ssl_options is not None or
                       ssl_options_explicit)

Comment thread cassandra/io/eventletreactor.py Outdated
Comment thread tests/unit/io/test_eventletreactor.py
Copilot AI review requested due to automatic review settings July 22, 2026 03:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

cassandra/datastax/insights/reporter.py:180

  • Connection always normalizes omitted options to self.ssl_options = {} (connection.py:1057). Preferring every non-None connection value here therefore makes a real plaintext control connection report sslConfigured.enabled: true, despite _ssl_options_explicit being false; the omitted-options test misses this because its mock has no ssl_options attribute. Only prefer the connection dictionary when it was explicitly supplied, otherwise fall back to the cluster value.
        ssl_options = (connection_ssl_options
                       if connection_ssl_options is not None
                       else self._session.cluster.ssl_options)
        ssl_options_explicit = bool(_safe_getattr(connection, '_ssl_options_explicit', False))
        ssl_enabled = (ssl_context is not None or
                       ssl_options is not None or
                       endpoint_ssl_options is not None or
                       ssl_options_explicit)

Copilot AI review requested due to automatic review settings July 22, 2026 03:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

cassandra/datastax/insights/reporter.py:176

  • A real Connection always normalizes omitted ssl_options=None to {} (connection.py:1057). Selecting any non-None connection options here therefore marks every plaintext control connection as SSL-enabled and reports certValidation: false. Use _ssl_options_explicit to distinguish that normalized empty mapping from supplied options before falling back to the cluster configuration.
        ssl_options = (connection_ssl_options
                       if connection_ssl_options is not None
                       else self._session.cluster.ssl_options)
        ssl_options_explicit = bool(_safe_getattr(connection, '_ssl_options_explicit', False))

Comment thread cassandra/connection.py
Copilot AI review requested due to automatic review settings July 22, 2026 03:53
@dkropachev
dkropachev force-pushed the fix-empty-ssl-options-reactors branch from 941469c to 5eb98b0 Compare July 22, 2026 03:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

cassandra/datastax/insights/reporter.py:176

  • Connection.__init__ always normalizes omitted options to connection.ssl_options = {} while leaving _ssl_options_explicit false. Because this selects any non-None connection value before checking explicitness, every real plaintext control connection is now treated as SSL-enabled (and reports certValidation: false). The omitted-options test misses this because its mock has no ssl_options attribute. Only prefer the connection options when they were explicit; otherwise fall back to the cluster value.
        ssl_options = (connection_ssl_options
                       if connection_ssl_options is not None
                       else self._session.cluster.ssl_options)
        ssl_options_explicit = bool(_safe_getattr(connection, '_ssl_options_explicit', False))

Comment thread cassandra/io/asyncioreactor.py
Copilot AI review requested due to automatic review settings July 22, 2026 03:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

cassandra/datastax/insights/reporter.py:176

  • Connection.__init__ always normalizes omitted options to self.ssl_options = {} (cassandra/connection.py:1071-1072). A real plaintext control connection therefore selects that empty dict here, and the following ssl_options is not None check reports SSL as enabled (and certificate validation as false). Gate connection-level options on _ssl_options_explicit before using them; the omitted-options test currently misses this because its mock leaves ssl_options absent.
        ssl_options = (connection_ssl_options
                       if connection_ssl_options is not None
                       else self._session.cluster.ssl_options)
        ssl_options_explicit = bool(_safe_getattr(connection, '_ssl_options_explicit', False))

Copilot AI review requested due to automatic review settings July 22, 2026 04:08
@dkropachev
dkropachev force-pushed the fix-empty-ssl-options-reactors branch from 5eb98b0 to d05df6c Compare July 22, 2026 04:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

cassandra/datastax/insights/reporter.py:175

  • Connection normalizes omitted options to self.ssl_options = {}, so a real plaintext control connection always makes connection_ssl_options is not None. This selection consequently reports TLS as enabled and certValidation as False even when both cluster SSL arguments were omitted; the mock-based omitted-options test misses that normalization. Only prefer the connection options when _ssl_options_explicit is true, otherwise fall back to the cluster value.
        ssl_options = (connection_ssl_options
                       if connection_ssl_options is not None
                       else self._session.cluster.ssl_options)

Comment thread cassandra/connection.py
Comment thread cassandra/datastax/insights/reporter.py Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 04:19
@dkropachev
dkropachev force-pushed the fix-empty-ssl-options-reactors branch from d05df6c to 3c6f515 Compare July 22, 2026 04:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

cassandra/datastax/insights/reporter.py:180

  • Connection.__init__ always normalizes omitted options to self.ssl_options = {}. On a real plaintext control connection, connection_ssl_options is therefore non-None, so this predicate reports Cluster() as SSL-enabled (and reports certificate validation as false) even though SSL was omitted. The test mock hides this by leaving the attribute absent. Select connection options only when _ssl_options_explicit is true; otherwise fall back to the cluster options.
        ssl_options_explicit = bool(_safe_getattr(connection, '_ssl_options_explicit', False))
        ssl_enabled = (ssl_context is not None or
                       ssl_options is not None or
                       endpoint_ssl_options is not None or
                       ssl_options_explicit)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Normalize explicit ssl_options={} handling across reactors and Insights

3 participants