Skip to content

Commit 6361fe0

Browse files
Fixes SSL params
Signed-off-by: Elena Kolevska <elena@kolevska.com>
1 parent dec029f commit 6361fe0

File tree

4 files changed

+77
-32
lines changed

4 files changed

+77
-32
lines changed

.env.example

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@ REDIS_DB=0
66
REDIS_CLUSTER=false
77
REDIS_CLUSTER_NODES=
88
REDIS_SSL=false
9+
REDIS_SSL_KEYFILE=
10+
REDIS_SSL_CERTFILE=
911
REDIS_SSL_CERT_REQS=required
1012
REDIS_SSL_CA_CERTS=
11-
REDIS_SSL_CERTFILE=
12-
REDIS_SSL_KEYFILE=
13+
REDIS_SSL_CA_PATH=
14+
REDIS_SSL_CA_DATA=
15+
REDIS_SSL_CHECK_HOSTNAME=true
16+
REDIS_SSL_PASSWORD=
17+
REDIS_SSL_VALIDATE_OCSP=false
18+
REDIS_SSL_VALIDATE_OCSP_STAPLED=false
19+
REDIS_SSL_CIPHERS=
1320
REDIS_RELAXED_TIMEOUT=
1421
REDIS_SOCKET_TIMEOUT=5.0
1522
REDIS_SOCKET_CONNECT_TIMEOUT=5.0

cli.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,17 @@ def describe_profile(profile_name):
119119
@click.option('--cluster', is_flag=True, default=lambda: get_env_or_default('REDIS_CLUSTER', False, bool), help='Use Redis Cluster mode')
120120
@click.option('--cluster-nodes', default=lambda: get_env_or_default('REDIS_CLUSTER_NODES', None), help='Comma-separated list of cluster nodes (host:port)')
121121
@click.option('--ssl', is_flag=True, default=lambda: get_env_or_default('REDIS_SSL', False, bool), help='Use SSL/TLS connection')
122+
@click.option('--ssl-keyfile', default=lambda: get_env_or_default('REDIS_SSL_KEYFILE', None), help='Path to client private key file')
123+
@click.option('--ssl-certfile', default=lambda: get_env_or_default('REDIS_SSL_CERTFILE', None), help='Path to client certificate file')
122124
@click.option('--ssl-cert-reqs', default=lambda: get_env_or_default('REDIS_SSL_CERT_REQS', 'required'), type=click.Choice(['none', 'optional', 'required']), help='SSL certificate requirements')
123125
@click.option('--ssl-ca-certs', default=lambda: get_env_or_default('REDIS_SSL_CA_CERTS', None), help='Path to CA certificates file')
124-
@click.option('--ssl-certfile', default=lambda: get_env_or_default('REDIS_SSL_CERTFILE', None), help='Path to client certificate file')
125-
@click.option('--ssl-keyfile', default=lambda: get_env_or_default('REDIS_SSL_KEYFILE', None), help='Path to client private key file')
126+
@click.option('--ssl-ca-path', default=lambda: get_env_or_default('REDIS_SSL_CA_PATH', None), help='Path to directory containing CA certificates')
127+
@click.option('--ssl-ca-data', default=lambda: get_env_or_default('REDIS_SSL_CA_DATA', None), help='CA certificate data as string')
128+
@click.option('--ssl-check-hostname', is_flag=True, default=lambda: get_env_or_default('REDIS_SSL_CHECK_HOSTNAME', True, bool), help='Check SSL hostname')
129+
@click.option('--ssl-password', default=lambda: get_env_or_default('REDIS_SSL_PASSWORD', None), help='Password for SSL private key')
130+
@click.option('--ssl-validate-ocsp', is_flag=True, default=lambda: get_env_or_default('REDIS_SSL_VALIDATE_OCSP', False, bool), help='Validate OCSP')
131+
@click.option('--ssl-validate-ocsp-stapled', is_flag=True, default=lambda: get_env_or_default('REDIS_SSL_VALIDATE_OCSP_STAPLED', False, bool), help='Validate OCSP stapled')
132+
@click.option('--ssl-ciphers', default=lambda: get_env_or_default('REDIS_SSL_CIPHERS', None), help='SSL cipher suite')
126133
@click.option('--socket-timeout', type=float, default=lambda: get_env_or_default('REDIS_SOCKET_TIMEOUT', None), help='Socket timeout in seconds')
127134
@click.option('--socket-connect-timeout', type=float, default=lambda: get_env_or_default('REDIS_SOCKET_CONNECT_TIMEOUT', None), help='Socket connect timeout in seconds')
128135
@click.option('--max-connections', type=int, default=lambda: get_env_or_default('REDIS_MAX_CONNECTIONS', 50, int), help='Maximum connections per client')
@@ -286,10 +293,17 @@ def _build_config_from_args(kwargs) -> RunnerConfig:
286293
cluster_mode=kwargs['cluster'],
287294
cluster_nodes=cluster_nodes,
288295
ssl=kwargs['ssl'],
296+
ssl_keyfile=kwargs['ssl_keyfile'],
297+
ssl_certfile=kwargs['ssl_certfile'],
289298
ssl_cert_reqs=kwargs['ssl_cert_reqs'],
290299
ssl_ca_certs=kwargs['ssl_ca_certs'],
291-
ssl_certfile=kwargs['ssl_certfile'],
292-
ssl_keyfile=kwargs['ssl_keyfile'],
300+
ssl_ca_path=kwargs['ssl_ca_path'],
301+
ssl_ca_data=kwargs['ssl_ca_data'],
302+
ssl_check_hostname=kwargs['ssl_check_hostname'],
303+
ssl_password=kwargs['ssl_password'],
304+
ssl_validate_ocsp=kwargs['ssl_validate_ocsp'],
305+
ssl_validate_ocsp_stapled=kwargs['ssl_validate_ocsp_stapled'],
306+
ssl_ciphers=kwargs['ssl_ciphers'],
293307
socket_timeout=kwargs['socket_timeout'],
294308
socket_connect_timeout=kwargs['socket_connect_timeout'],
295309
max_connections=kwargs['max_connections'],

config.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Configuration management for Redis test application.
33
"""
44
from dataclasses import dataclass, field
5-
from typing import Dict, List, Optional, Any
5+
from typing import Dict, List, Optional, Any, Union
66
import yaml
77
import json
88
import importlib.metadata
@@ -90,10 +90,20 @@ class RedisConnectionConfig:
9090

9191
# TLS configuration
9292
ssl: bool = False
93-
ssl_cert_reqs: str = "required"
94-
ssl_ca_certs: Optional[str] = None
95-
ssl_certfile: Optional[str] = None
9693
ssl_keyfile: Optional[str] = None
94+
ssl_certfile: Optional[str] = None
95+
ssl_cert_reqs: Union[str, int] = "required" # Can be "required", "optional", "none" or ssl.VerifyMode
96+
ssl_ca_certs: Optional[str] = None
97+
ssl_ca_path: Optional[str] = None
98+
ssl_ca_data: Optional[str] = None
99+
ssl_check_hostname: bool = True
100+
ssl_password: Optional[str] = None
101+
ssl_validate_ocsp: bool = False
102+
ssl_validate_ocsp_stapled: bool = False
103+
ssl_ocsp_context: Optional[Any] = None # OpenSSL.SSL.Context
104+
ssl_ocsp_expected_cert: Optional[str] = None
105+
ssl_min_version: Optional[Any] = None # ssl.TLSVersion
106+
ssl_ciphers: Optional[str] = None
97107

98108
# Connection settings
99109
socket_timeout: Optional[float] = None

redis_client.py

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from redis.exceptions import (
1212
ConnectionError, TimeoutError, ClusterDownError
1313
)
14-
import ssl
14+
1515

1616
from config import RedisConnectionConfig
1717
from logger import get_logger
@@ -58,26 +58,39 @@ def _build_pool_kwargs(self) -> Dict[str, Any]:
5858

5959
# Add SSL configuration if enabled
6060
if self.config.ssl:
61-
ssl_context = ssl.create_default_context()
62-
63-
if self.config.ssl_cert_reqs == "none":
64-
ssl_context.check_hostname = False
65-
ssl_context.verify_mode = ssl.CERT_NONE
66-
elif self.config.ssl_cert_reqs == "optional":
67-
ssl_context.verify_mode = ssl.CERT_OPTIONAL
68-
else:
69-
ssl_context.verify_mode = ssl.CERT_REQUIRED
70-
71-
if self.config.ssl_ca_certs:
72-
ssl_context.load_verify_locations(self.config.ssl_ca_certs)
73-
74-
if self.config.ssl_certfile and self.config.ssl_keyfile:
75-
ssl_context.load_cert_chain(self.config.ssl_certfile, self.config.ssl_keyfile)
76-
77-
kwargs.update({
78-
'ssl': True,
79-
'ssl_context': ssl_context
80-
})
61+
ssl_kwargs = {'ssl': True}
62+
63+
# Add SSL parameters directly as redis-py expects them
64+
if self.config.ssl_keyfile is not None:
65+
ssl_kwargs['ssl_keyfile'] = self.config.ssl_keyfile
66+
if self.config.ssl_certfile is not None:
67+
ssl_kwargs['ssl_certfile'] = self.config.ssl_certfile
68+
if self.config.ssl_cert_reqs is not None:
69+
ssl_kwargs['ssl_cert_reqs'] = self.config.ssl_cert_reqs
70+
if self.config.ssl_ca_certs is not None:
71+
ssl_kwargs['ssl_ca_certs'] = self.config.ssl_ca_certs
72+
if self.config.ssl_ca_path is not None:
73+
ssl_kwargs['ssl_ca_path'] = self.config.ssl_ca_path
74+
if self.config.ssl_ca_data is not None:
75+
ssl_kwargs['ssl_ca_data'] = self.config.ssl_ca_data
76+
if self.config.ssl_check_hostname is not None:
77+
ssl_kwargs['ssl_check_hostname'] = self.config.ssl_check_hostname
78+
if self.config.ssl_password is not None:
79+
ssl_kwargs['ssl_password'] = self.config.ssl_password
80+
if self.config.ssl_validate_ocsp is not None:
81+
ssl_kwargs['ssl_validate_ocsp'] = self.config.ssl_validate_ocsp
82+
if self.config.ssl_validate_ocsp_stapled is not None:
83+
ssl_kwargs['ssl_validate_ocsp_stapled'] = self.config.ssl_validate_ocsp_stapled
84+
if self.config.ssl_ocsp_context is not None:
85+
ssl_kwargs['ssl_ocsp_context'] = self.config.ssl_ocsp_context
86+
if self.config.ssl_ocsp_expected_cert is not None:
87+
ssl_kwargs['ssl_ocsp_expected_cert'] = self.config.ssl_ocsp_expected_cert
88+
if self.config.ssl_min_version is not None:
89+
ssl_kwargs['ssl_min_version'] = self.config.ssl_min_version
90+
if self.config.ssl_ciphers is not None:
91+
ssl_kwargs['ssl_ciphers'] = self.config.ssl_ciphers
92+
93+
kwargs.update(ssl_kwargs)
8194

8295
return kwargs
8396

@@ -110,6 +123,8 @@ def _connect_standalone(self):
110123
"""Connect to standalone Redis instance."""
111124
start_time = time.time()
112125

126+
print("\n\n\n ------- Pool kwargs:", {**self._pool_kwargs})
127+
113128
if self.config.maintenance_notifications_enabled:
114129
# Build maintenance events config, only passing relaxed_timeouts if not None
115130
maintenance_config_kwargs = {"enabled": self.config.maintenance_notifications_enabled}
@@ -126,7 +141,6 @@ def _connect_standalone(self):
126141
**self._pool_kwargs
127142
)
128143
else:
129-
print("\n\n\n self._pool_kwargs", self._pool_kwargs)
130144
self._client = redis.Redis(
131145
host=self.config.host,
132146
port=self.config.port,

0 commit comments

Comments
 (0)