Skip to content

Commit 680bb4d

Browse files
authored
Merge pull request #280 from raiden-network/feature/federation-whitelist-reloader
Add runtime reloading of the federation whitelist
2 parents d4324a4 + 766a389 commit 680bb4d

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)