mas_config/sections/
mod.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
6
7use rand::Rng;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10
11mod account;
12mod branding;
13mod captcha;
14mod clients;
15mod database;
16mod email;
17mod experimental;
18mod http;
19mod matrix;
20mod passwords;
21mod policy;
22mod rate_limiting;
23mod secrets;
24mod telemetry;
25mod templates;
26mod upstream_oauth2;
27
28pub use self::{
29    account::AccountConfig,
30    branding::BrandingConfig,
31    captcha::{CaptchaConfig, CaptchaServiceKind},
32    clients::{ClientAuthMethodConfig, ClientConfig, ClientsConfig},
33    database::{DatabaseConfig, PgSslMode},
34    email::{EmailConfig, EmailSmtpMode, EmailTransportKind},
35    experimental::ExperimentalConfig,
36    http::{
37        BindConfig as HttpBindConfig, HttpConfig, ListenerConfig as HttpListenerConfig,
38        Resource as HttpResource, TlsConfig as HttpTlsConfig, UnixOrTcp,
39    },
40    matrix::{HomeserverKind, MatrixConfig},
41    passwords::{
42        Algorithm as PasswordAlgorithm, HashingScheme as PasswordHashingScheme, PasswordsConfig,
43    },
44    policy::PolicyConfig,
45    rate_limiting::RateLimitingConfig,
46    secrets::SecretsConfig,
47    telemetry::{
48        MetricsConfig, MetricsExporterKind, Propagator, TelemetryConfig, TracingConfig,
49        TracingExporterKind,
50    },
51    templates::TemplatesConfig,
52    upstream_oauth2::{
53        ClaimsImports as UpstreamOAuth2ClaimsImports, DiscoveryMode as UpstreamOAuth2DiscoveryMode,
54        EmailImportPreference as UpstreamOAuth2EmailImportPreference,
55        ImportAction as UpstreamOAuth2ImportAction, PkceMethod as UpstreamOAuth2PkceMethod,
56        Provider as UpstreamOAuth2Provider, ResponseMode as UpstreamOAuth2ResponseMode,
57        TokenAuthMethod as UpstreamOAuth2TokenAuthMethod, UpstreamOAuth2Config,
58    },
59};
60use crate::util::ConfigurationSection;
61
62/// Application configuration root
63#[derive(Debug, Serialize, Deserialize, JsonSchema)]
64pub struct RootConfig {
65    /// List of OAuth 2.0/OIDC clients config
66    #[serde(default, skip_serializing_if = "ClientsConfig::is_default")]
67    pub clients: ClientsConfig,
68
69    /// Configuration of the HTTP server
70    #[serde(default)]
71    pub http: HttpConfig,
72
73    /// Database connection configuration
74    #[serde(default)]
75    pub database: DatabaseConfig,
76
77    /// Configuration related to sending monitoring data
78    #[serde(default, skip_serializing_if = "TelemetryConfig::is_default")]
79    pub telemetry: TelemetryConfig,
80
81    /// Configuration related to templates
82    #[serde(default, skip_serializing_if = "TemplatesConfig::is_default")]
83    pub templates: TemplatesConfig,
84
85    /// Configuration related to sending emails
86    #[serde(default)]
87    pub email: EmailConfig,
88
89    /// Application secrets
90    pub secrets: SecretsConfig,
91
92    /// Configuration related to user passwords
93    #[serde(default)]
94    pub passwords: PasswordsConfig,
95
96    /// Configuration related to the homeserver
97    pub matrix: MatrixConfig,
98
99    /// Configuration related to the OPA policies
100    #[serde(default, skip_serializing_if = "PolicyConfig::is_default")]
101    pub policy: PolicyConfig,
102
103    /// Configuration related to limiting the rate of user actions to prevent
104    /// abuse
105    #[serde(default, skip_serializing_if = "RateLimitingConfig::is_default")]
106    pub rate_limiting: RateLimitingConfig,
107
108    /// Configuration related to upstream OAuth providers
109    #[serde(default, skip_serializing_if = "UpstreamOAuth2Config::is_default")]
110    pub upstream_oauth2: UpstreamOAuth2Config,
111
112    /// Configuration section for tweaking the branding of the service
113    #[serde(default, skip_serializing_if = "BrandingConfig::is_default")]
114    pub branding: BrandingConfig,
115
116    /// Configuration section to setup CAPTCHA protection on a few operations
117    #[serde(default, skip_serializing_if = "CaptchaConfig::is_default")]
118    pub captcha: CaptchaConfig,
119
120    /// Configuration section to configure features related to account
121    /// management
122    #[serde(default, skip_serializing_if = "AccountConfig::is_default")]
123    pub account: AccountConfig,
124
125    /// Experimental configuration options
126    #[serde(default, skip_serializing_if = "ExperimentalConfig::is_default")]
127    pub experimental: ExperimentalConfig,
128}
129
130impl ConfigurationSection for RootConfig {
131    fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
132        self.clients.validate(figment)?;
133        self.http.validate(figment)?;
134        self.database.validate(figment)?;
135        self.telemetry.validate(figment)?;
136        self.templates.validate(figment)?;
137        self.email.validate(figment)?;
138        self.passwords.validate(figment)?;
139        self.secrets.validate(figment)?;
140        self.matrix.validate(figment)?;
141        self.policy.validate(figment)?;
142        self.rate_limiting.validate(figment)?;
143        self.upstream_oauth2.validate(figment)?;
144        self.branding.validate(figment)?;
145        self.captcha.validate(figment)?;
146        self.account.validate(figment)?;
147        self.experimental.validate(figment)?;
148
149        Ok(())
150    }
151}
152
153impl RootConfig {
154    /// Generate a new configuration with random secrets
155    ///
156    /// # Errors
157    ///
158    /// Returns an error if the secrets could not be generated
159    pub async fn generate<R>(mut rng: R) -> anyhow::Result<Self>
160    where
161        R: Rng + Send,
162    {
163        Ok(Self {
164            clients: ClientsConfig::default(),
165            http: HttpConfig::default(),
166            database: DatabaseConfig::default(),
167            telemetry: TelemetryConfig::default(),
168            templates: TemplatesConfig::default(),
169            email: EmailConfig::default(),
170            passwords: PasswordsConfig::default(),
171            secrets: SecretsConfig::generate(&mut rng).await?,
172            matrix: MatrixConfig::generate(&mut rng),
173            policy: PolicyConfig::default(),
174            rate_limiting: RateLimitingConfig::default(),
175            upstream_oauth2: UpstreamOAuth2Config::default(),
176            branding: BrandingConfig::default(),
177            captcha: CaptchaConfig::default(),
178            account: AccountConfig::default(),
179            experimental: ExperimentalConfig::default(),
180        })
181    }
182
183    /// Configuration used in tests
184    #[must_use]
185    pub fn test() -> Self {
186        Self {
187            clients: ClientsConfig::default(),
188            http: HttpConfig::default(),
189            database: DatabaseConfig::default(),
190            telemetry: TelemetryConfig::default(),
191            templates: TemplatesConfig::default(),
192            passwords: PasswordsConfig::default(),
193            email: EmailConfig::default(),
194            secrets: SecretsConfig::test(),
195            matrix: MatrixConfig::test(),
196            policy: PolicyConfig::default(),
197            rate_limiting: RateLimitingConfig::default(),
198            upstream_oauth2: UpstreamOAuth2Config::default(),
199            branding: BrandingConfig::default(),
200            captcha: CaptchaConfig::default(),
201            account: AccountConfig::default(),
202            experimental: ExperimentalConfig::default(),
203        }
204    }
205}
206
207/// Partial configuration actually used by the server
208#[allow(missing_docs)]
209#[derive(Debug, Deserialize)]
210pub struct AppConfig {
211    #[serde(default)]
212    pub http: HttpConfig,
213
214    #[serde(default)]
215    pub database: DatabaseConfig,
216
217    #[serde(default)]
218    pub templates: TemplatesConfig,
219
220    #[serde(default)]
221    pub email: EmailConfig,
222
223    pub secrets: SecretsConfig,
224
225    #[serde(default)]
226    pub passwords: PasswordsConfig,
227
228    pub matrix: MatrixConfig,
229
230    #[serde(default)]
231    pub policy: PolicyConfig,
232
233    #[serde(default)]
234    pub rate_limiting: RateLimitingConfig,
235
236    #[serde(default)]
237    pub branding: BrandingConfig,
238
239    #[serde(default)]
240    pub captcha: CaptchaConfig,
241
242    #[serde(default)]
243    pub account: AccountConfig,
244
245    #[serde(default)]
246    pub experimental: ExperimentalConfig,
247}
248
249impl ConfigurationSection for AppConfig {
250    fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
251        self.http.validate(figment)?;
252        self.database.validate(figment)?;
253        self.templates.validate(figment)?;
254        self.email.validate(figment)?;
255        self.passwords.validate(figment)?;
256        self.secrets.validate(figment)?;
257        self.matrix.validate(figment)?;
258        self.policy.validate(figment)?;
259        self.rate_limiting.validate(figment)?;
260        self.branding.validate(figment)?;
261        self.captcha.validate(figment)?;
262        self.account.validate(figment)?;
263        self.experimental.validate(figment)?;
264
265        Ok(())
266    }
267}
268
269/// Partial config used by the `mas-cli config sync` command
270#[allow(missing_docs)]
271#[derive(Debug, Deserialize)]
272pub struct SyncConfig {
273    #[serde(default)]
274    pub database: DatabaseConfig,
275
276    pub secrets: SecretsConfig,
277
278    #[serde(default)]
279    pub clients: ClientsConfig,
280
281    #[serde(default)]
282    pub upstream_oauth2: UpstreamOAuth2Config,
283}
284
285impl ConfigurationSection for SyncConfig {
286    fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
287        self.database.validate(figment)?;
288        self.secrets.validate(figment)?;
289        self.clients.validate(figment)?;
290        self.upstream_oauth2.validate(figment)?;
291
292        Ok(())
293    }
294}