Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/17984.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `recaptcha_private_key_path` and `recaptcha_public_key_path` config option.
30 changes: 30 additions & 0 deletions docs/usage/configuration/config_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2357,6 +2357,21 @@ Example configuration:
recaptcha_public_key: YOUR_PUBLIC_KEY
```
---
### `recaptcha_public_key_path`

*(string|null)* An alternative to [`recaptcha_public_key`](#recaptcha_public_key): allows the public key to be specified in an external file.

The file should be a plain text file, containing only the public key. Synapse reads the public key from the given file once at startup.

_Added in Synapse 1.134.0._

Defaults to `null`.

Example configuration:
```yaml
recaptcha_public_key_path: /path/to/key/file
```
---
### `recaptcha_private_key`

*(string|null)* This homeserver's ReCAPTCHA private key. Must be specified if [`enable_registration_captcha`](#enable_registration_captcha) is enabled. Defaults to `null`.
Expand All @@ -2366,6 +2381,21 @@ Example configuration:
recaptcha_private_key: YOUR_PRIVATE_KEY
```
---
### `recaptcha_private_key_path`

*(string|null)* An alternative to [`recaptcha_private_key`](#recaptcha_private_key): allows the private key to be specified in an external file.

The file should be a plain text file, containing only the private key. Synapse reads the private key from the given file once at startup.

_Added in Synapse 1.134.0._

Defaults to `null`.

Example configuration:
```yaml
recaptcha_private_key_path: /path/to/key/file
```
---
### `enable_registration_captcha`

*(boolean)* Set to `true` to require users to complete a CAPTCHA test when registering an account. Requires a valid ReCaptcha public/private key.
Expand Down
30 changes: 30 additions & 0 deletions schema/synapse-config.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2692,6 +2692,21 @@ properties:
default: null
examples:
- YOUR_PUBLIC_KEY
recaptcha_public_key_path:
type: ["string", "null"]
description: >-
An alternative to [`recaptcha_public_key`](#recaptcha_public_key): allows
the public key to be specified in an external file.


The file should be a plain text file, containing only the public key.
Synapse reads the public key from the given file once at startup.


_Added in Synapse 1.134.0._
default: null
examples:
- /path/to/key/file
recaptcha_private_key:
type: ["string", "null"]
description: >-
Expand All @@ -2700,6 +2715,21 @@ properties:
default: null
examples:
- YOUR_PRIVATE_KEY
recaptcha_private_key_path:
type: ["string", "null"]
description: >-
An alternative to [`recaptcha_private_key`](#recaptcha_private_key):
allows the private key to be specified in an external file.


The file should be a plain text file, containing only the private key.
Synapse reads the private key from the given file once at startup.


_Added in Synapse 1.134.0._
default: null
examples:
- /path/to/key/file
enable_registration_captcha:
type: boolean
description: >-
Expand Down
26 changes: 25 additions & 1 deletion synapse/config/captcha.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@

from synapse.types import JsonDict

from ._base import Config, ConfigError
from ._base import Config, ConfigError, read_file

CONFLICTING_RECAPTCHA_PRIVATE_KEY_OPTS_ERROR = """\
You have configured both `recaptcha_private_key` and
`recaptcha_private_key_path`. These are mutually incompatible.
"""

CONFLICTING_RECAPTCHA_PUBLIC_KEY_OPTS_ERROR = """\
You have configured both `recaptcha_public_key` and `recaptcha_public_key_path`.
These are mutually incompatible.
"""


class CaptchaConfig(Config):
Expand All @@ -38,6 +48,13 @@ def read_config(
"Config options that expect an in-line secret as value are disabled",
("recaptcha_private_key",),
)
recaptcha_private_key_path = config.get("recaptcha_private_key_path")
if recaptcha_private_key_path:
if recaptcha_private_key:
raise ConfigError(CONFLICTING_RECAPTCHA_PRIVATE_KEY_OPTS_ERROR)
recaptcha_private_key = read_file(
recaptcha_private_key_path, ("recaptcha_private_key_path",)
).strip()
if recaptcha_private_key is not None and not isinstance(
recaptcha_private_key, str
):
Expand All @@ -50,6 +67,13 @@ def read_config(
"Config options that expect an in-line secret as value are disabled",
("recaptcha_public_key",),
)
recaptcha_public_key_path = config.get("recaptcha_public_key_path")
if recaptcha_public_key_path:
if recaptcha_public_key:
raise ConfigError(CONFLICTING_RECAPTCHA_PUBLIC_KEY_OPTS_ERROR)
recaptcha_public_key = read_file(
recaptcha_public_key_path, ("recaptcha_public_key_path",)
).strip()
if recaptcha_public_key is not None and not isinstance(
recaptcha_public_key, str
):
Expand Down
10 changes: 10 additions & 0 deletions tests/config/test_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ def test_depreciated_identity_server_flag_throws_error(self) -> None:
"turn_shared_secret_path: /does/not/exist",
"registration_shared_secret_path: /does/not/exist",
"macaroon_secret_key_path: /does/not/exist",
"recaptcha_private_key_path: /does/not/exist",
"recaptcha_public_key_path: /does/not/exist",
"form_secret_path: /does/not/exist",
"worker_replication_secret_path: /does/not/exist",
"experimental_features:\n msc3861:\n client_secret_path: /does/not/exist",
Expand Down Expand Up @@ -167,6 +169,14 @@ def test_secret_files_missing(self, config_str: str) -> None:
"macaroon_secret_key_path: {}",
lambda c: c.key.macaroon_secret_key,
),
(
"recaptcha_private_key_path: {}",
lambda c: c.captcha.recaptcha_private_key.encode("utf-8"),
),
(
"recaptcha_public_key_path: {}",
lambda c: c.captcha.recaptcha_public_key.encode("utf-8"),
),
(
"form_secret_path: {}",
lambda c: c.key.form_secret.encode("utf-8"),
Expand Down
Loading