Skip to content

Commit 766a389

Browse files
committed
Add runtime reloading of the federation whitelist
Previously the 'purger' service would periodically check if the configured whitelist of known federation servers was still up to date and if not restart the affected synapse services. That caused downtime and also was a somewhat annoying workaround. This now introduces a module that checks and updates the configuration at runtime without the need for a restart. Note that this is accessing Synapse internals that aren't considered stable and therefore subject to change with future version upgrades.
1 parent d4324a4 commit 766a389

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

build/synapse/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ RUN sed -i 's/\(\s*\)if self.worker_type/\1if True or self.worker_type/' /synaps
3030

3131
COPY eth_auth_provider.py /synapse-venv/lib/python3.9/site-packages/
3232
COPY admin_user_auth_provider.py /synapse-venv/lib/python3.9/site-packages/
33+
COPY federation_whitelist_reloader.py /synapse-venv/lib/python3.9/site-packages/
3334
COPY synapse-entrypoint.sh /bin/
3435
COPY render_config_template.py /bin/
3536
COPY --from=RAIDEN /known_servers.default.txt /
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import logging
2+
import os
3+
from pathlib import Path
4+
from typing import Any, Dict
5+
6+
from synapse.api.errors import HttpResponseException
7+
from synapse.handlers.auth import AuthHandler
8+
9+
10+
# This file gets created during docker build from the given Raiden version
11+
from synapse.http import RequestTimedOutError
12+
from synapse.metrics.background_process_metrics import run_as_background_process
13+
14+
15+
PATH_KNOWN_FEDERATION_SERVERS_DEFAULT_URL = Path("/known_servers.default.txt")
16+
17+
18+
class FederationWhitelistReloaderProvider:
19+
"""
20+
Helper that peridoically fetches and updates the allowed federation domain whitelist.
21+
22+
Implemented as a password provider since this is a handy way to inject code into Synapse.
23+
"""
24+
25+
__version__ = "0.1"
26+
27+
def __init__(self, config: Dict[str, Any], account_handler: AuthHandler) -> None:
28+
self.hs = account_handler._hs
29+
self.known_servers_url = os.environ.get(
30+
"URL_KNOWN_FEDERATION_SERVERS", PATH_KNOWN_FEDERATION_SERVERS_DEFAULT_URL.read_text()
31+
)
32+
self.update_interval = config.get("update_interval", 3600)
33+
self.log = logging.getLogger(__name__)
34+
self.clock = self.hs.get_clock()
35+
self.clock.call_later(0, self.run_check_and_fetch_in_background)
36+
37+
@staticmethod
38+
def parse_config(config: Dict[str, Any]) -> Dict[str, Any]:
39+
return config
40+
41+
def run_check_and_fetch_in_background(self) -> None:
42+
run_as_background_process(
43+
"federation_whitelist_reloader", self._check_and_update_whitelist
44+
)
45+
46+
async def _check_and_update_whitelist(self) -> None:
47+
http_client = self.hs.get_proxied_blacklisted_http_client()
48+
try:
49+
known_servers = await http_client.get_json(self.known_servers_url)
50+
if not isinstance(known_servers, dict):
51+
raise TypeError(f"Invalid response format from known servers URL: {known_servers}")
52+
if "all_servers" not in known_servers:
53+
raise ValueError(
54+
f"Known servers response is missing 'all_serves' key: {known_servers}"
55+
)
56+
new_whitelist = known_servers["all_servers"]
57+
self.hs.config.federation_domain_whitelist = {domain: True for domain in new_whitelist}
58+
self.log.warning("Updated federation whitelist. New list: %s", new_whitelist)
59+
except (HttpResponseException, RequestTimedOutError, TypeError, ValueError) as ex:
60+
self.log.error(f"Error fetching federation known servers: {ex}. Will retry later.")
61+
self.clock.call_later(self.update_interval, self.run_check_and_fetch_in_background)

config/synapse/synapse.template.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ password_providers:
117117
config:
118118
enabled: true
119119
credentials_file: /config/admin_user_cred.json
120+
- module: 'federation_whitelist_reloader.FederationWhitelistReloaderProvider'
121+
config:
122+
enabled: true
120123

121124
bcrypt_rounds: 12
122125

0 commit comments

Comments
 (0)