You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-06 06:02:40 +03:00
New config options to set the database certificates
This commit is contained in:
@@ -228,6 +228,54 @@ fn database_connect_options_from_config(
|
||||
opts
|
||||
};
|
||||
|
||||
let options = match (config.ssl_ca.as_deref(), config.ssl_ca_file.as_deref()) {
|
||||
(None, None) => options,
|
||||
(Some(pem), None) => options.ssl_root_cert_from_pem(pem.as_bytes().to_owned()),
|
||||
(None, Some(path)) => options.ssl_root_cert(path),
|
||||
(Some(_), Some(_)) => {
|
||||
anyhow::bail!("invalid database configuration: both `ssl_ca` and `ssl_ca_file` are set")
|
||||
}
|
||||
};
|
||||
|
||||
let options = match (
|
||||
config.ssl_certificate.as_deref(),
|
||||
config.ssl_certificate_file.as_deref(),
|
||||
) {
|
||||
(None, None) => options,
|
||||
(Some(pem), None) => options.ssl_client_cert_from_pem(pem.as_bytes()),
|
||||
(None, Some(path)) => options.ssl_client_cert(path),
|
||||
(Some(_), Some(_)) => {
|
||||
anyhow::bail!("invalid database configuration: both `ssl_certificate` and `ssl_certificate_file` are set")
|
||||
}
|
||||
};
|
||||
|
||||
let options = match (config.ssl_key.as_deref(), config.ssl_key_file.as_deref()) {
|
||||
(None, None) => options,
|
||||
(Some(pem), None) => options.ssl_client_key_from_pem(pem.as_bytes()),
|
||||
(None, Some(path)) => options.ssl_client_key(path),
|
||||
(Some(_), Some(_)) => {
|
||||
anyhow::bail!(
|
||||
"invalid database configuration: both `ssl_key` and `ssl_key_file` are set"
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let options = match &config.ssl_mode {
|
||||
Some(ssl_mode) => {
|
||||
let ssl_mode = match ssl_mode {
|
||||
mas_config::PgSslMode::Disable => sqlx::postgres::PgSslMode::Disable,
|
||||
mas_config::PgSslMode::Allow => sqlx::postgres::PgSslMode::Allow,
|
||||
mas_config::PgSslMode::Prefer => sqlx::postgres::PgSslMode::Prefer,
|
||||
mas_config::PgSslMode::Require => sqlx::postgres::PgSslMode::Require,
|
||||
mas_config::PgSslMode::VerifyCa => sqlx::postgres::PgSslMode::VerifyCa,
|
||||
mas_config::PgSslMode::VerifyFull => sqlx::postgres::PgSslMode::VerifyFull,
|
||||
};
|
||||
|
||||
options.ssl_mode(ssl_mode)
|
||||
}
|
||||
None => options,
|
||||
};
|
||||
|
||||
let options = options
|
||||
.log_statements(LevelFilter::Debug)
|
||||
.log_slow_statements(LevelFilter::Warn, Duration::from_millis(100));
|
||||
|
@@ -55,6 +55,13 @@ impl Default for DatabaseConfig {
|
||||
username: None,
|
||||
password: None,
|
||||
database: None,
|
||||
ssl_mode: None,
|
||||
ssl_ca: None,
|
||||
ssl_ca_file: None,
|
||||
ssl_certificate: None,
|
||||
ssl_certificate_file: None,
|
||||
ssl_key: None,
|
||||
ssl_key_file: None,
|
||||
max_connections: default_max_connections(),
|
||||
min_connections: Default::default(),
|
||||
connect_timeout: default_connect_timeout(),
|
||||
@@ -64,6 +71,34 @@ impl Default for DatabaseConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Options for controlling the level of protection provided for PostgreSQL SSL
|
||||
/// connections.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum PgSslMode {
|
||||
/// Only try a non-SSL connection.
|
||||
Disable,
|
||||
|
||||
/// First try a non-SSL connection; if that fails, try an SSL connection.
|
||||
Allow,
|
||||
|
||||
/// First try an SSL connection; if that fails, try a non-SSL connection.
|
||||
Prefer,
|
||||
|
||||
/// Only try an SSL connection. If a root CA file is present, verify the
|
||||
/// connection in the same way as if `VerifyCa` was specified.
|
||||
Require,
|
||||
|
||||
/// Only try an SSL connection, and verify that the server certificate is
|
||||
/// issued by a trusted certificate authority (CA).
|
||||
VerifyCa,
|
||||
|
||||
/// Only try an SSL connection; verify that the server certificate is issued
|
||||
/// by a trusted CA and that the requested server host name matches that
|
||||
/// in the certificate.
|
||||
VerifyFull,
|
||||
}
|
||||
|
||||
/// Database connection configuration
|
||||
#[serde_as]
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||
@@ -115,6 +150,50 @@ pub struct DatabaseConfig {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub database: Option<String>,
|
||||
|
||||
/// How to handle SSL connections
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ssl_mode: Option<PgSslMode>,
|
||||
|
||||
/// The PEM-encoded root certificate for SSL connections
|
||||
///
|
||||
/// This must not be specified if the `ssl_ca_file` option is specified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ssl_ca: Option<String>,
|
||||
|
||||
/// Path to the root certificate for SSL connections
|
||||
///
|
||||
/// This must not be specified if the `ssl_ca` option is specified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(with = "Option<String>")]
|
||||
pub ssl_ca_file: Option<Utf8PathBuf>,
|
||||
|
||||
/// The PEM-encoded client certificate for SSL connections
|
||||
///
|
||||
/// This must not be specified if the `ssl_certificate_file` option is
|
||||
/// specified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ssl_certificate: Option<String>,
|
||||
|
||||
/// Path to the client certificate for SSL connections
|
||||
///
|
||||
/// This must not be specified if the `ssl_certificate` option is specified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(with = "Option<String>")]
|
||||
pub ssl_certificate_file: Option<Utf8PathBuf>,
|
||||
|
||||
/// The PEM-encoded client key for SSL connections
|
||||
///
|
||||
/// This must not be specified if the `ssl_key_file` option is specified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ssl_key: Option<String>,
|
||||
|
||||
/// Path to the client key for SSL connections
|
||||
///
|
||||
/// This must not be specified if the `ssl_key` option is specified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(with = "Option<String>")]
|
||||
pub ssl_key_file: Option<Utf8PathBuf>,
|
||||
|
||||
/// Set the maximum number of connections the pool should maintain
|
||||
#[serde(default = "default_max_connections")]
|
||||
pub max_connections: NonZeroU32,
|
||||
@@ -153,6 +232,12 @@ impl ConfigurationSection for DatabaseConfig {
|
||||
|
||||
fn validate(&self, figment: &figment::Figment) -> Result<(), figment::error::Error> {
|
||||
let metadata = figment.find_metadata(Self::PATH.unwrap());
|
||||
let annotate = |mut error: figment::Error| {
|
||||
error.metadata = metadata.cloned();
|
||||
error.profile = Some(figment::Profile::Default);
|
||||
error.path = vec![Self::PATH.unwrap().to_owned()];
|
||||
Err(error)
|
||||
};
|
||||
|
||||
// Check that the user did not specify both `uri` and the split options at the
|
||||
// same time
|
||||
@@ -164,19 +249,42 @@ impl ConfigurationSection for DatabaseConfig {
|
||||
|| self.database.is_some();
|
||||
|
||||
if self.uri.is_some() && has_split_options {
|
||||
let mut error = figment::error::Error::from(
|
||||
return annotate(figment::error::Error::from(
|
||||
"uri must not be specified if host, port, socket, username, password, or database are specified".to_owned(),
|
||||
);
|
||||
error.metadata = metadata.cloned();
|
||||
error.profile = Some(figment::Profile::Default);
|
||||
error.path = vec![Self::PATH.unwrap().to_owned(), "uri".to_owned()];
|
||||
return Err(error);
|
||||
));
|
||||
}
|
||||
|
||||
if self.ssl_ca.is_some() && self.ssl_ca_file.is_some() {
|
||||
return annotate(figment::error::Error::from(
|
||||
"ssl_ca must not be specified if ssl_ca_file is specified".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
if self.ssl_certificate.is_some() && self.ssl_certificate_file.is_some() {
|
||||
return annotate(figment::error::Error::from(
|
||||
"ssl_certificate must not be specified if ssl_certificate_file is specified"
|
||||
.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
if self.ssl_key.is_some() && self.ssl_key_file.is_some() {
|
||||
return annotate(figment::error::Error::from(
|
||||
"ssl_key must not be specified if ssl_key_file is specified".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
if (self.ssl_key.is_some() || self.ssl_key_file.is_some())
|
||||
^ (self.ssl_certificate.is_some() || self.ssl_certificate_file.is_some())
|
||||
{
|
||||
return annotate(figment::error::Error::from(
|
||||
"both a ssl_certificate and a ssl_key must be set at the same time or none of them"
|
||||
.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use figment::{
|
||||
|
@@ -35,7 +35,7 @@ pub use self::{
|
||||
branding::BrandingConfig,
|
||||
captcha::{CaptchaConfig, CaptchaServiceKind},
|
||||
clients::{ClientAuthMethodConfig, ClientConfig, ClientsConfig},
|
||||
database::DatabaseConfig,
|
||||
database::{DatabaseConfig, PgSslMode},
|
||||
email::{EmailConfig, EmailSmtpMode, EmailTransportKind},
|
||||
experimental::ExperimentalConfig,
|
||||
http::{
|
||||
|
@@ -1003,6 +1003,38 @@
|
||||
"description": "The database name\n\nThis must not be specified if `uri` is specified.",
|
||||
"type": "string"
|
||||
},
|
||||
"ssl_mode": {
|
||||
"description": "How to handle SSL connections",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PgSslMode"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ssl_ca": {
|
||||
"description": "The PEM-encoded root certificate for SSL connections\n\nThis must not be specified if the `ssl_ca_file` option is specified.",
|
||||
"type": "string"
|
||||
},
|
||||
"ssl_ca_file": {
|
||||
"description": "Path to the root certificate for SSL connections\n\nThis must not be specified if the `ssl_ca` option is specified.",
|
||||
"type": "string"
|
||||
},
|
||||
"ssl_certificate": {
|
||||
"description": "The PEM-encoded client certificate for SSL connections\n\nThis must not be specified if the `ssl_certificate_file` option is specified.",
|
||||
"type": "string"
|
||||
},
|
||||
"ssl_certificate_file": {
|
||||
"description": "Path to the client certificate for SSL connections\n\nThis must not be specified if the `ssl_certificate` option is specified.",
|
||||
"type": "string"
|
||||
},
|
||||
"ssl_key": {
|
||||
"description": "The PEM-encoded client key for SSL connections\n\nThis must not be specified if the `ssl_key_file` option is specified.",
|
||||
"type": "string"
|
||||
},
|
||||
"ssl_key_file": {
|
||||
"description": "Path to the client key for SSL connections\n\nThis must not be specified if the `ssl_key` option is specified.",
|
||||
"type": "string"
|
||||
},
|
||||
"max_connections": {
|
||||
"description": "Set the maximum number of connections the pool should maintain",
|
||||
"default": 10,
|
||||
@@ -1044,6 +1076,53 @@
|
||||
"type": "string",
|
||||
"format": "hostname"
|
||||
},
|
||||
"PgSslMode": {
|
||||
"description": "Options for controlling the level of protection provided for PostgreSQL SSL connections.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Only try a non-SSL connection.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "First try a non-SSL connection; if that fails, try an SSL connection.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"allow"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "First try an SSL connection; if that fails, try a non-SSL connection.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"prefer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Only try an SSL connection. If a root CA file is present, verify the connection in the same way as if `VerifyCa` was specified.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"require"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Only try an SSL connection, and verify that the server certificate is issued by a trusted certificate authority (CA).",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"verify-ca"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Only try an SSL connection; verify that the server certificate is issued by a trusted CA and that the requested server host name matches that in the certificate.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"verify-full"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"TelemetryConfig": {
|
||||
"description": "Configuration related to sending monitoring data",
|
||||
"type": "object",
|
||||
|
Reference in New Issue
Block a user