implement error_on_unknown_config_opts, slightly improve related code

Signed-off-by: June Strawberry <june@vern.cc>
This commit is contained in:
June Strawberry
2026-01-29 17:19:44 -05:00
parent 13ad2c7966
commit fbeaed1c15
8 changed files with 56 additions and 20 deletions

View File

@@ -62,8 +62,8 @@ COPY <<EOF complement.toml
database_path = "/database" database_path = "/database"
dns_attempts = 20 dns_attempts = 20
dns_timeout = 60 dns_timeout = 60
error_on_unknown_config_opts = true
federation_idle_timeout = 300 federation_idle_timeout = 300
intentionally_unknown_config_option_for_testing = true
ip_range_denylist = [] ip_range_denylist = []
log = "debug,tuwunel=trace,h2=warn,hyper=warn" log = "debug,tuwunel=trace,h2=warn,hyper=warn"
log_colors = false log_colors = false

View File

@@ -35,6 +35,7 @@ COPY <<EOF tuwunel.toml
allow_public_room_directory_without_auth = true allow_public_room_directory_without_auth = true
allow_registration = true allow_registration = true
create_admin_room = false create_admin_room = false
error_on_unknown_config_opts = true
ip_range_denylist = [] ip_range_denylist = []
log = "debug,tuwunel=trace,h2=warn,hyper=warn" log = "debug,tuwunel=trace,h2=warn,hyper=warn"
log_colors = false log_colors = false

View File

@@ -65,6 +65,7 @@ RUN \
-- \ -- \
-Otest='["smoke", "fresh"]' \ -Otest='["smoke", "fresh"]' \
-Oserver_name=\"localhost\" \ -Oserver_name=\"localhost\" \
-Oerror_on_unknown_config_opts=true \
EOF EOF

View File

@@ -19,7 +19,8 @@ RUN <<EOF
tuwunel \ tuwunel \
-Otest='["smoke"]' \ -Otest='["smoke"]' \
-Oserver_name=\"localhost\" \ -Oserver_name=\"localhost\" \
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" -Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" \
-Oerror_on_unknown_config_opts=true
rm -rf "${TUWUNEL_DATABASE_PATH}" rm -rf "${TUWUNEL_DATABASE_PATH}"
EOF EOF
@@ -44,7 +45,8 @@ RUN <<EOF
-Otest='["smoke"]' \ -Otest='["smoke"]' \
-Oserver_name=\"localhost\" \ -Oserver_name=\"localhost\" \
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" \ -Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" \
-Odb_pool_max_workers=${db_pool_max_workers} -Odb_pool_max_workers=${db_pool_max_workers} \
-Oerror_on_unknown_config_opts=true
rm -rf "${TUWUNEL_DATABASE_PATH}" rm -rf "${TUWUNEL_DATABASE_PATH}"
EOF EOF
@@ -62,7 +64,8 @@ RUN <<EOF
tuwunel \ tuwunel \
-Otest='["smoke"]' \ -Otest='["smoke"]' \
-Oserver_name=\"localhost\" \ -Oserver_name=\"localhost\" \
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" -Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" \
-Oerror_on_unknown_config_opts=true
rm -rf "${TUWUNEL_DATABASE_PATH}" rm -rf "${TUWUNEL_DATABASE_PATH}"
EOF EOF

View File

@@ -6,6 +6,7 @@ allow_public_room_directory_over_federation = true
allow_public_room_directory_without_auth = true allow_public_room_directory_without_auth = true
allow_registration = true allow_registration = true
database_path = "/database" database_path = "/database"
error_on_unknown_config_opts = true
log = "trace,h2=debug,hyper=debug" log = "trace,h2=debug,hyper=debug"
port = [8008, 8448] port = [8008, 8448]
trusted_servers = [] trusted_servers = []

View File

@@ -2,6 +2,7 @@ use std::env::consts::OS;
use either::Either; use either::Either;
use figment::Figment; use figment::Figment;
use itertools::Itertools;
use super::{DEPRECATED_KEYS, IdentityProvider}; use super::{DEPRECATED_KEYS, IdentityProvider};
use crate::{Config, Err, Result, Server, debug, debug_info, debug_warn, error, warn}; use crate::{Config, Err, Result, Server, debug, debug_info, debug_warn, error, warn};
@@ -35,7 +36,7 @@ pub fn check(config: &Config) -> Result {
} }
warn_deprecated(config); warn_deprecated(config);
warn_unknown_key(config); warn_unknown_key(config)?;
if config.sentry && config.sentry_endpoint.is_none() { if config.sentry && config.sentry_endpoint.is_none() {
return Err!(Config( return Err!(Config(
@@ -358,34 +359,47 @@ pub fn check(config: &Config) -> Result {
/// deprecated key specified /// deprecated key specified
fn warn_deprecated(config: &Config) { fn warn_deprecated(config: &Config) {
debug!("Checking for deprecated config keys"); debug!("Checking for deprecated config keys");
let mut was_deprecated = false; let found_deprecated_keys = config
for key in config
.catchall .catchall
.keys() .keys()
.filter(|key| DEPRECATED_KEYS.iter().any(|s| s == key)) .filter(|key| DEPRECATED_KEYS.iter().any(|s| s == key))
{ .inspect(|key| warn!("Config parameter \"{key}\" is deprecated, ignoring."))
warn!("Config parameter \"{}\" is deprecated, ignoring.", key); .next()
was_deprecated = true; .is_some();
}
if was_deprecated { if found_deprecated_keys {
warn!( warn!(
"Read tuwunel config documentation at https://tuwunel.chat/configuration.html and \ "Deprecated config keys were found. Read tuwunel config documentation at https://tuwunel.chat/configuration.html and \
check your configuration if any new configuration parameters should be adjusted" check your configuration if any new configuration parameters should be adjusted"
); );
} }
} }
/// iterates over all the catchall keys (unknown config options) and warns /// iterates over all the catchall keys (unknown config options) and warns or
/// if there are any. /// errors if there are any.
fn warn_unknown_key(config: &Config) { fn warn_unknown_key(config: &Config) -> Result {
debug!("Checking for unknown config keys"); debug!("Checking for unknown config keys");
for key in config let unknown_keys = config
.catchall .catchall
.keys() .keys()
.filter(|key| "config".to_owned().ne(key.to_owned()) /* "config" is expected */) .filter_map(|key| {
{ if key == "config" {
warn!("Config parameter \"{}\" is unknown to tuwunel, ignoring.", key); None
} else {
if config.error_on_unknown_config_opts {
error!("Config parameter \"{key}\" is unknown to tuwunel");
} else {
warn!("Config parameter \"{key}\" is unknown to tuwunel, ignoring.");
}
Some(key.as_str())
}
})
.collect_vec();
if !unknown_keys.is_empty() && config.error_on_unknown_config_opts {
Err!("Unknown config options were found: {unknown_keys:?}")
} else {
Ok(())
} }
} }

View File

@@ -146,6 +146,14 @@ pub struct Config {
#[serde(default = "default_unix_socket_perms")] #[serde(default = "default_unix_socket_perms")]
pub unix_socket_perms: u32, pub unix_socket_perms: u32,
/// Error on startup if any config option specified is unknown to Tuwunel.
///
/// This is false by default to allow easier deprecation or removal of
/// config options in the future without breaking existing deployments. The
/// default behaviour is to simply warn on startup.
#[serde(default)]
pub error_on_unknown_config_opts: bool,
/// tuwunel supports online database backups using RocksDB's Backup engine /// tuwunel supports online database backups using RocksDB's Backup engine
/// API. To use this, set a database backup path that tuwunel can write /// API. To use this, set a database backup path that tuwunel can write
/// to. /// to.

View File

@@ -89,6 +89,14 @@
# #
#unix_socket_perms = 660 #unix_socket_perms = 660
# Error on startup if any config option specified is unknown to Tuwunel.
#
# This is false by default to allow easier deprecation or removal of
# config options in the future without breaking existing deployments. The
# default behaviour is to simply warn on startup.
#
#error_on_unknown_config_opts = false
# tuwunel supports online database backups using RocksDB's Backup engine # tuwunel supports online database backups using RocksDB's Backup engine
# API. To use this, set a database backup path that tuwunel can write # API. To use this, set a database backup path that tuwunel can write
# to. # to.