Skip to content

Fix SSL verification with ssl_cert_reqs="none" and ssl_check_hostname=True #3637

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

omerfeyzioglu
Copy link

Pull Request check-list

Please make sure to review and check all of these items:

  • Do tests and lints pass with this change?
  • Do the CI tests pass with this change (enable it first in your forked repo and wait for the github action build to finish)?
  • Is the new or changed code fully tested?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?
  • Is there an example added to the examples folder (if applicable)?
  • Was the change added to CHANGES file?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Description of change

Fix SSL verification with ssl_cert_reqs="none" and ssl_check_hostname=True

Problem

When connecting to a Redis cluster with SSL enabled, the following error occurs when trying to set ssl_check_hostname=True along with ssl_cert_reqs="none":
Fail to establish redis connection: Redis Cluster cannot be connected. Please provide at least one reachable node: Cannot set verify_mode to CERT_NONE when check_hostname is enabled.

This is because of a limitation in Python's SSL library that prevents check_hostname=True from being used with verify_mode=ssl.CERT_NONE.

Solution

This PR fixes the issue by:

  1. Automatically setting check_hostname=False when verify_mode=ssl.CERT_NONE in both:

    • redis/asyncio/connection.py for async clients
    • redis/connection.py for sync clients
  2. Adding tests to verify the fix works correctly in both sync and async modes.

Notes

This issue is particularly relevant after the 6.0.0 release which changed the default value of ssl_check_hostname to True for improved security. This fix ensures a smoother transition for users who need to use ssl_cert_reqs="none" while maintaining compatibility with this new default setting.

The fix ensures that when users set ssl_cert_reqs="none" (or use ssl.CERT_NONE), hostname verification will be automatically disabled to prevent this error, while still respecting explicit ssl_check_hostname=False settings when certificate verification is enabled.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes an SSL-related bug where using ssl_cert_reqs="none" alongside ssl_check_hostname=True would trigger an error during connection establishment. The changes ensure that when certificate verification is disabled (i.e., ssl_cert_reqs is set to "none"), the check_hostname flag is automatically set to False for both synchronous and asynchronous clients.

  • Updated connection logic in both sync (redis/connection.py) and async (redis/asyncio/connection.py) modules to enforce check_hostname=False when ssl_cert_reqs is ssl.CERT_NONE.
  • Added tests in tests/test_ssl.py and tests/test_asyncio/test_ssl.py to verify the fix in both sync and async contexts.

Reviewed Changes

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

File Description
tests/test_ssl.py Added a synchronous test to verify automatic disabling of hostname checking for SSL connections.
tests/test_asyncio/test_ssl.py Added an asynchronous test to verify automatic disabling of hostname checking for SSL connections.
redis/connection.py Modified sync connection to disable hostname check when ssl_cert_reqs is ssl.CERT_NONE.
redis/asyncio/connection.py Modified async connection to disable hostname check when ssl_cert_reqs is ssl.CERT_NONE.
Files not reviewed (1)
  • CHANGES: Language not supported

Comment on lines +317 to +320
p = urlparse(ssl_url)[1].split(":")
r = redis.Redis(
host=p[0],
port=p[1],
Copy link
Preview

Copilot AI May 7, 2025

Choose a reason for hiding this comment

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

Consider using urlparse(ssl_url).hostname and urlparse(ssl_url).port for better clarity and robustness instead of indexing the parsed URL result.

Suggested change
p = urlparse(ssl_url)[1].split(":")
r = redis.Redis(
host=p[0],
port=p[1],
parsed_url = urlparse(ssl_url)
r = redis.Redis(
host=parsed_url.hostname,
port=parsed_url.port,

Copilot uses AI. Check for mistakes.

Comment on lines +26 to +28
ssl_url = request.config.option.redis_ssl_url
p = urlparse(ssl_url)[1].split(":")
client = redis.Redis(host=p[0], port=p[1], ssl=True)
Copy link
Preview

Copilot AI May 7, 2025

Choose a reason for hiding this comment

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

Consider using urlparse(ssl_url).hostname and urlparse(ssl_url).port for clarity and better error-proofing of the URL parsing.

Suggested change
ssl_url = request.config.option.redis_ssl_url
p = urlparse(ssl_url)[1].split(":")
client = redis.Redis(host=p[0], port=p[1], ssl=True)
ssl_url = request.config.option.redis_ssl_url
parsed_url = urlparse(ssl_url)
client = redis.Redis(host=parsed_url.hostname, port=parsed_url.port, ssl=True)

Copilot uses AI. Check for mistakes.

Copy link
Collaborator

@petyaslavova petyaslavova left a comment

Choose a reason for hiding this comment

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

The logic to set check_hostname=False when cert_reqs is None makes sense, but it doesn't fully address the underlying issue—it mostly masks it.

To resolve this properly, we should ensure that ssl_check_hostname passed through kwargs is propagated to the connection initialization. In cluster.py, there's a tuple called REDIS_ALLOWED_KEYS - adding ssl_check_hostname there would prevent it from being stripped from kwargs.

Also, since this change affects behavior demonstrated in the examples, could you please take a look at the documentation updated in PR #3626 and remove the explicit ssl_check_hostname=False setting if it’s no longer necessary?
It will also be good if you could change the tests in which cert_reqs is set to none not to provide explicitly ssl_check_hostname=False.

@petyaslavova
Copy link
Collaborator

@omerfeyzioglu, thank you so much for taking the time and putting in the effort to prepare this contribution — it's truly appreciated!

@petyaslavova petyaslavova added maintenance Maintenance (CI, Releases, etc) bug Bug labels May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug maintenance Maintenance (CI, Releases, etc)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants