Skip to content

Commit

Permalink
An federation whitelist query endpoint extension
Browse files Browse the repository at this point in the history
  • Loading branch information
erikjohnston committed Jan 24, 2024
1 parent c925b45 commit 15a9878
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 0 deletions.
31 changes: 31 additions & 0 deletions docs/usage/configuration/config_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4541,3 +4541,34 @@ background_updates:
min_batch_size: 10
default_batch_size: 50
```


---
## Extension features
Configuration for extension features for Synapse

---
### `extension_federation_whitelist_endpoint`

Enables an endpoint for fetching the federation whitelist config.

The request path is `/_synapse/client/config/federation_whitelist`, and the
response format is:

```json
{
"whitelist_enabled": true, // Whether there is a federation whitelist
"whitelist": [ // Which hosts are allowed by the whitelist
"example.com"
]
}
```

If `whitelist_enabled` is `false` then the server can federate with all others.

The endpoint requires authentication.

Example configuration:
```yaml
extension_federation_whitelist_endpoint: true
```
2 changes: 2 additions & 0 deletions synapse/config/_base.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ from synapse.config import ( # noqa: F401
database,
emailconfig,
experimental,
extensions,
federation,
jwt,
key,
Expand Down Expand Up @@ -120,6 +121,7 @@ class RootConfig:
federation: federation.FederationConfig
retention: retention.RetentionConfig
background_updates: background_updates.BackgroundUpdateConfig
extensions: extensions.ExtensionsConfig

config_classes: List[Type["Config"]] = ...
config_files: List[str]
Expand Down
29 changes: 29 additions & 0 deletions synapse/config/extensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# This file is licensed under the Affero General Public License (AGPL) version 3.
#
# Copyright (C) 2023 New Vector, Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# See the GNU Affero General Public License for more details:
# <https://www.gnu.org/licenses/agpl-3.0.html>.
#

from typing import Any

from synapse.config._base import Config
from synapse.types import JsonDict


class ExtensionsConfig(Config):
"""Config section for enabling extension features"""

section = "extensions"

def read_config(self, config: JsonDict, **kwargs: Any) -> None:
self.federation_whitelist_endpoint: bool = config.get(
"extension_federation_whitelist_endpoint", False
)
2 changes: 2 additions & 0 deletions synapse/config/homeserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from .database import DatabaseConfig
from .emailconfig import EmailConfig
from .experimental import ExperimentalConfig
from .extensions import ExtensionsConfig
from .federation import FederationConfig
from .jwt import JWTConfig
from .key import KeyConfig
Expand Down Expand Up @@ -105,4 +106,5 @@ class HomeServerConfig(RootConfig):
RedisConfig,
ExperimentalConfig,
BackgroundUpdateConfig,
ExtensionsConfig,
]
4 changes: 4 additions & 0 deletions synapse/rest/synapse/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from twisted.web.resource import Resource

from synapse.rest.synapse.client.federation_whitelist import FederationWhitelistResource
from synapse.rest.synapse.client.new_user_consent import NewUserConsentResource
from synapse.rest.synapse.client.pick_idp import PickIdpResource
from synapse.rest.synapse.client.pick_username import pick_username_resource
Expand Down Expand Up @@ -76,6 +77,9 @@ def build_synapse_client_resource_tree(hs: "HomeServer") -> Mapping[str, Resourc
# To be removed in Synapse v1.32.0.
resources["/_matrix/saml2"] = res

if hs.config.extensions.federation_whitelist_endpoint:
resources[FederationWhitelistResource.PATH] = FederationWhitelistResource(hs)

return resources


Expand Down
72 changes: 72 additions & 0 deletions synapse/rest/synapse/client/federation_whitelist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#
# This file is licensed under the Affero General Public License (AGPL) version 3.
#
# Copyright (C) 2024 New Vector, Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# See the GNU Affero General Public License for more details:
# <https://www.gnu.org/licenses/agpl-3.0.html>.
#

import logging
from typing import TYPE_CHECKING, Generator, List, Tuple

from twisted.web.resource import Resource
from twisted.web.server import Request

from synapse.api.errors import SynapseError
from synapse.handlers.sso import get_username_mapping_session_cookie_from_request
from synapse.http.server import (
DirectServeHtmlResource,
DirectServeJsonResource,
respond_with_html,
)
from synapse.http.servlet import parse_boolean, parse_string
from synapse.http.site import SynapseRequest
from synapse.types import JsonDict
from synapse.util.templates import build_jinja_env

if TYPE_CHECKING:
from synapse.server import HomeServer

logger = logging.getLogger(__name__)


class FederationWhitelistResource(DirectServeJsonResource):
"""Custom endpoint (disabled by default) to fetch the federation whitelist
config.
Only enabled if `federation_whitelist_endpoint` extension feature is enabled.
Response format:
{
"whitelist_enabled": true, // Whether there is a federation whitelist
"whitelist": [ // Which hosts are allowed by the whitelist
"example.com"
]
}
"""

PATH = "/_synapse/client/config/federation_whitelist"

def __init__(self, hs: "HomeServer"):
super().__init__()

self._federation_whitelist = hs.config.federation.federation_domain_whitelist

self._auth = hs.get_auth()

async def _async_render_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
await self._auth.get_user_by_req(request)

return_dict = {
"whitelist_enabled": self._federation_whitelist is not None,
"whitelist": self._federation_whitelist or [],
}

return 200, return_dict

0 comments on commit 15a9878

Please sign in to comment.