Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 2611433

Browse files
authored
Add redis SSL configuration options (#15312)
* Add SSL options to redis config * fix lint issues * Add documentation and changelog file * add missing . at the end of the changelog * Move client context factory to new file * Rename ssl to tls and fix typo * fix lint issues * Added when redis attributes were added
1 parent 5bf9ec9 commit 2611433

File tree

7 files changed

+98
-14
lines changed

7 files changed

+98
-14
lines changed

changelog.d/15312.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add redis TLS configuration options.

contrib/docker_compose_workers/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ redis:
7070
port: 6379
7171
# dbid: <redis_logical_db_id>
7272
# password: <secret_password>
73+
# use_tls: True
74+
# certificate_file: <path_to_certificate>
75+
# private_key_file: <path_to_private_key>
76+
# ca_file: <path_to_ca_certificate>
7377
```
7478

7579
This assumes that your Redis service is called `redis` in your Docker Compose file.

docs/usage/configuration/config_documentation.md

+11
Original file line numberDiff line numberDiff line change
@@ -3981,9 +3981,16 @@ This setting has the following sub-options:
39813981
localhost and 6379
39823982
* `password`: Optional password if configured on the Redis instance.
39833983
* `dbid`: Optional redis dbid if needs to connect to specific redis logical db.
3984+
* `use_tls`: Whether to use tls connection. Defaults to false.
3985+
* `certificate_file`: Optional path to the certificate file
3986+
* `private_key_file`: Optional path to the private key file
3987+
* `ca_file`: Optional path to the CA certificate file. Use this one or:
3988+
* `ca_path`: Optional path to the folder containing the CA certificate file
39843989

39853990
_Added in Synapse 1.78.0._
39863991

3992+
_Changed in Synapse 1.84.0: Added use\_tls, certificate\_file, private\_key\_file, ca\_file and ca\_path attributes_
3993+
39873994
Example configuration:
39883995
```yaml
39893996
redis:
@@ -3992,6 +3999,10 @@ redis:
39923999
port: 6379
39934000
password: <secret_password>
39944001
dbid: <dbid>
4002+
#use_tls: True
4003+
#certificate_file: <path_to_the_certificate_file>
4004+
#private_key_file: <path_to_the_private_key_file>
4005+
#ca_file: <path_to_the_ca_certificate_file>
39954006
```
39964007
---
39974008
## Individual worker configuration

synapse/config/redis.py

+6
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,9 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
3535
self.redis_port = redis_config.get("port", 6379)
3636
self.redis_dbid = redis_config.get("dbid", None)
3737
self.redis_password = redis_config.get("password")
38+
39+
self.redis_use_tls = redis_config.get("use_tls", False)
40+
self.redis_certificate = redis_config.get("certificate_file", None)
41+
self.redis_private_key = redis_config.get("private_key_file", None)
42+
self.redis_ca_file = redis_config.get("ca_file", None)
43+
self.redis_ca_path = redis_config.get("ca_path", None)

synapse/replication/tcp/context.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2023 The Matrix.org Foundation C.I.C.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from OpenSSL.SSL import Context
15+
from twisted.internet import ssl
16+
17+
from synapse.config.redis import RedisConfig
18+
19+
20+
class ClientContextFactory(ssl.ClientContextFactory):
21+
def __init__(self, redis_config: RedisConfig):
22+
self.redis_config = redis_config
23+
24+
def getContext(self) -> Context:
25+
ctx = super().getContext()
26+
if self.redis_config.redis_certificate:
27+
ctx.use_certificate_file(self.redis_config.redis_certificate)
28+
if self.redis_config.redis_private_key:
29+
ctx.use_privatekey_file(self.redis_config.redis_private_key)
30+
if self.redis_config.redis_ca_file:
31+
ctx.load_verify_locations(cafile=self.redis_config.redis_ca_file)
32+
elif self.redis_config.redis_ca_path:
33+
ctx.load_verify_locations(capath=self.redis_config.redis_ca_path)
34+
return ctx

synapse/replication/tcp/handler.py

+22-7
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
UserIpCommand,
4747
UserSyncCommand,
4848
)
49+
from synapse.replication.tcp.context import ClientContextFactory
4950
from synapse.replication.tcp.protocol import IReplicationConnection
5051
from synapse.replication.tcp.streams import (
5152
STREAMS_MAP,
@@ -348,13 +349,27 @@ def start_replication(self, hs: "HomeServer") -> None:
348349
outbound_redis_connection,
349350
channel_names=self._channels_to_subscribe_to,
350351
)
351-
hs.get_reactor().connectTCP(
352-
hs.config.redis.redis_host,
353-
hs.config.redis.redis_port,
354-
self._factory,
355-
timeout=30,
356-
bindAddress=None,
357-
)
352+
353+
reactor = hs.get_reactor()
354+
redis_config = hs.config.redis
355+
if hs.config.redis.redis_use_tls:
356+
ssl_context_factory = ClientContextFactory(hs.config.redis)
357+
reactor.connectSSL(
358+
redis_config.redis_host,
359+
redis_config.redis_port,
360+
self._factory,
361+
ssl_context_factory,
362+
timeout=30,
363+
bindAddress=None,
364+
)
365+
else:
366+
reactor.connectTCP(
367+
redis_config.redis_host,
368+
redis_config.redis_port,
369+
self._factory,
370+
timeout=30,
371+
bindAddress=None,
372+
)
358373

359374
def get_streams(self) -> Dict[str, Stream]:
360375
"""Get a map from stream name to all streams."""

synapse/replication/tcp/redis.py

+20-7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
ReplicateCommand,
3636
parse_command_from_line,
3737
)
38+
from synapse.replication.tcp.context import ClientContextFactory
3839
from synapse.replication.tcp.protocol import (
3940
IReplicationConnection,
4041
tcp_inbound_commands_counter,
@@ -386,12 +387,24 @@ def lazyConnection(
386387
factory.continueTrying = reconnect
387388

388389
reactor = hs.get_reactor()
389-
reactor.connectTCP(
390-
host,
391-
port,
392-
factory,
393-
timeout=30,
394-
bindAddress=None,
395-
)
390+
391+
if hs.config.redis.redis_use_tls:
392+
ssl_context_factory = ClientContextFactory(hs.config.redis)
393+
reactor.connectSSL(
394+
host,
395+
port,
396+
factory,
397+
ssl_context_factory,
398+
timeout=30,
399+
bindAddress=None,
400+
)
401+
else:
402+
reactor.connectTCP(
403+
host,
404+
port,
405+
factory,
406+
timeout=30,
407+
bindAddress=None,
408+
)
396409

397410
return factory.handler

0 commit comments

Comments
 (0)