Skip to content

Commit 481c4e2

Browse files
authored
Add recaptcha_{private,public}_key_path config option (#17984)
Another config option on my quest to a `*_path` variant for every secret. Adds the config options `recaptcha_private_key_path` and `recaptcha_public_key_path`. Tests and docs are included. A public key is of course no secret, but it is closely related to the private key, so it’s still useful to have a `*_path` variant for it.
1 parent 5129668 commit 481c4e2

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

changelog.d/17984.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `recaptcha_private_key_path` and `recaptcha_public_key_path` config option.

docs/usage/configuration/config_documentation.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,6 +2357,21 @@ Example configuration:
23572357
recaptcha_public_key: YOUR_PUBLIC_KEY
23582358
```
23592359
---
2360+
### `recaptcha_public_key_path`
2361+
2362+
*(string|null)* An alternative to [`recaptcha_public_key`](#recaptcha_public_key): allows the public key to be specified in an external file.
2363+
2364+
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.
2365+
2366+
_Added in Synapse 1.134.0._
2367+
2368+
Defaults to `null`.
2369+
2370+
Example configuration:
2371+
```yaml
2372+
recaptcha_public_key_path: /path/to/key/file
2373+
```
2374+
---
23602375
### `recaptcha_private_key`
23612376

23622377
*(string|null)* This homeserver's ReCAPTCHA private key. Must be specified if [`enable_registration_captcha`](#enable_registration_captcha) is enabled. Defaults to `null`.
@@ -2366,6 +2381,21 @@ Example configuration:
23662381
recaptcha_private_key: YOUR_PRIVATE_KEY
23672382
```
23682383
---
2384+
### `recaptcha_private_key_path`
2385+
2386+
*(string|null)* An alternative to [`recaptcha_private_key`](#recaptcha_private_key): allows the private key to be specified in an external file.
2387+
2388+
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.
2389+
2390+
_Added in Synapse 1.134.0._
2391+
2392+
Defaults to `null`.
2393+
2394+
Example configuration:
2395+
```yaml
2396+
recaptcha_private_key_path: /path/to/key/file
2397+
```
2398+
---
23692399
### `enable_registration_captcha`
23702400

23712401
*(boolean)* Set to `true` to require users to complete a CAPTCHA test when registering an account. Requires a valid ReCaptcha public/private key.

schema/synapse-config.schema.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,6 +2692,21 @@ properties:
26922692
default: null
26932693
examples:
26942694
- YOUR_PUBLIC_KEY
2695+
recaptcha_public_key_path:
2696+
type: ["string", "null"]
2697+
description: >-
2698+
An alternative to [`recaptcha_public_key`](#recaptcha_public_key): allows
2699+
the public key to be specified in an external file.
2700+
2701+
2702+
The file should be a plain text file, containing only the public key.
2703+
Synapse reads the public key from the given file once at startup.
2704+
2705+
2706+
_Added in Synapse 1.134.0._
2707+
default: null
2708+
examples:
2709+
- /path/to/key/file
26952710
recaptcha_private_key:
26962711
type: ["string", "null"]
26972712
description: >-
@@ -2700,6 +2715,21 @@ properties:
27002715
default: null
27012716
examples:
27022717
- YOUR_PRIVATE_KEY
2718+
recaptcha_private_key_path:
2719+
type: ["string", "null"]
2720+
description: >-
2721+
An alternative to [`recaptcha_private_key`](#recaptcha_private_key):
2722+
allows the private key to be specified in an external file.
2723+
2724+
2725+
The file should be a plain text file, containing only the private key.
2726+
Synapse reads the private key from the given file once at startup.
2727+
2728+
2729+
_Added in Synapse 1.134.0._
2730+
default: null
2731+
examples:
2732+
- /path/to/key/file
27032733
enable_registration_captcha:
27042734
type: boolean
27052735
description: >-

synapse/config/captcha.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,17 @@
2323

2424
from synapse.types import JsonDict
2525

26-
from ._base import Config, ConfigError
26+
from ._base import Config, ConfigError, read_file
27+
28+
CONFLICTING_RECAPTCHA_PRIVATE_KEY_OPTS_ERROR = """\
29+
You have configured both `recaptcha_private_key` and
30+
`recaptcha_private_key_path`. These are mutually incompatible.
31+
"""
32+
33+
CONFLICTING_RECAPTCHA_PUBLIC_KEY_OPTS_ERROR = """\
34+
You have configured both `recaptcha_public_key` and `recaptcha_public_key_path`.
35+
These are mutually incompatible.
36+
"""
2737

2838

2939
class CaptchaConfig(Config):
@@ -38,6 +48,13 @@ def read_config(
3848
"Config options that expect an in-line secret as value are disabled",
3949
("recaptcha_private_key",),
4050
)
51+
recaptcha_private_key_path = config.get("recaptcha_private_key_path")
52+
if recaptcha_private_key_path:
53+
if recaptcha_private_key:
54+
raise ConfigError(CONFLICTING_RECAPTCHA_PRIVATE_KEY_OPTS_ERROR)
55+
recaptcha_private_key = read_file(
56+
recaptcha_private_key_path, ("recaptcha_private_key_path",)
57+
).strip()
4158
if recaptcha_private_key is not None and not isinstance(
4259
recaptcha_private_key, str
4360
):
@@ -50,6 +67,13 @@ def read_config(
5067
"Config options that expect an in-line secret as value are disabled",
5168
("recaptcha_public_key",),
5269
)
70+
recaptcha_public_key_path = config.get("recaptcha_public_key_path")
71+
if recaptcha_public_key_path:
72+
if recaptcha_public_key:
73+
raise ConfigError(CONFLICTING_RECAPTCHA_PUBLIC_KEY_OPTS_ERROR)
74+
recaptcha_public_key = read_file(
75+
recaptcha_public_key_path, ("recaptcha_public_key_path",)
76+
).strip()
5377
if recaptcha_public_key is not None and not isinstance(
5478
recaptcha_public_key, str
5579
):

tests/config/test_load.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ def test_depreciated_identity_server_flag_throws_error(self) -> None:
138138
"turn_shared_secret_path: /does/not/exist",
139139
"registration_shared_secret_path: /does/not/exist",
140140
"macaroon_secret_key_path: /does/not/exist",
141+
"recaptcha_private_key_path: /does/not/exist",
142+
"recaptcha_public_key_path: /does/not/exist",
141143
"form_secret_path: /does/not/exist",
142144
"worker_replication_secret_path: /does/not/exist",
143145
"experimental_features:\n msc3861:\n client_secret_path: /does/not/exist",
@@ -167,6 +169,14 @@ def test_secret_files_missing(self, config_str: str) -> None:
167169
"macaroon_secret_key_path: {}",
168170
lambda c: c.key.macaroon_secret_key,
169171
),
172+
(
173+
"recaptcha_private_key_path: {}",
174+
lambda c: c.captcha.recaptcha_private_key.encode("utf-8"),
175+
),
176+
(
177+
"recaptcha_public_key_path: {}",
178+
lambda c: c.captcha.recaptcha_public_key.encode("utf-8"),
179+
),
170180
(
171181
"form_secret_path: {}",
172182
lambda c: c.key.form_secret.encode("utf-8"),

0 commit comments

Comments
 (0)