diff --git a/docker/Dockerfile.complement b/docker/Dockerfile.complement index 9d459a87..42fa2df9 100644 --- a/docker/Dockerfile.complement +++ b/docker/Dockerfile.complement @@ -62,8 +62,8 @@ COPY < Result { } warn_deprecated(config); - warn_unknown_key(config); + warn_unknown_key(config)?; if config.sentry && config.sentry_endpoint.is_none() { return Err!(Config( @@ -358,34 +359,47 @@ pub fn check(config: &Config) -> Result { /// deprecated key specified fn warn_deprecated(config: &Config) { debug!("Checking for deprecated config keys"); - let mut was_deprecated = false; - for key in config + let found_deprecated_keys = config .catchall .keys() .filter(|key| DEPRECATED_KEYS.iter().any(|s| s == key)) - { - warn!("Config parameter \"{}\" is deprecated, ignoring.", key); - was_deprecated = true; - } + .inspect(|key| warn!("Config parameter \"{key}\" is deprecated, ignoring.")) + .next() + .is_some(); - if was_deprecated { + if found_deprecated_keys { 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" ); } } -/// iterates over all the catchall keys (unknown config options) and warns -/// if there are any. -fn warn_unknown_key(config: &Config) { +/// iterates over all the catchall keys (unknown config options) and warns or +/// errors if there are any. +fn warn_unknown_key(config: &Config) -> Result { debug!("Checking for unknown config keys"); - for key in config + let unknown_keys = config .catchall .keys() - .filter(|key| "config".to_owned().ne(key.to_owned()) /* "config" is expected */) - { - warn!("Config parameter \"{}\" is unknown to tuwunel, ignoring.", key); + .filter_map(|key| { + if key == "config" { + 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(()) } } diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index 78610dd1..e2601467 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -146,6 +146,14 @@ pub struct Config { #[serde(default = "default_unix_socket_perms")] 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 /// API. To use this, set a database backup path that tuwunel can write /// to. diff --git a/tuwunel-example.toml b/tuwunel-example.toml index fd834fab..a86d4937 100644 --- a/tuwunel-example.toml +++ b/tuwunel-example.toml @@ -89,6 +89,14 @@ # #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 # API. To use this, set a database backup path that tuwunel can write # to.