From 8b088e30093102c0d93a0116d946d0e0750b74a1 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 17 Jun 2024 19:34:56 +0100 Subject: [PATCH] feat: [#878] extract tsl_config in toml config TSL configuration for HTTP trackers and the Tracker API is still optional. However, when it's provided is enabled. The `ssl_enabled` field was removed. You can remove the whole `tsl_config` to disable TSL. If you want to kee a copy in the TOML file you can just comment the lines. ```toml [[http_trackers]] ... [http_trackers.tsl_config] ssl_cert_path = "./storage/tracker/lib/tls/localhost.crt" ssl_key_path = "./storage/tracker/lib/tls/localhost.key" [http_api] ... [http_api.tsl_config] ssl_cert_path = "./storage/tracker/lib/tls/localhost.crt" ssl_key_path = "./storage/tracker/lib/tls/localhost.key" ``` --- Cargo.toml | 2 +- docs/containers.md | 23 +++--- packages/configuration/Cargo.toml | 2 +- packages/configuration/src/lib.rs | 17 +++-- packages/configuration/src/v1/http_tracker.rs | 19 +++-- packages/configuration/src/v1/mod.rs | 20 ++---- packages/configuration/src/v1/tracker_api.rs | 19 +++-- .../config/tracker.container.mysql.toml | 8 +-- .../config/tracker.container.sqlite3.toml | 8 --- .../config/tracker.e2e.container.sqlite3.toml | 6 -- src/bootstrap/jobs/http_tracker.rs | 2 +- src/bootstrap/jobs/mod.rs | 70 +++++++++---------- src/bootstrap/jobs/tracker_apis.rs | 2 +- src/lib.rs | 13 +--- src/servers/apis/mod.rs | 6 +- src/servers/apis/server.rs | 2 +- src/servers/http/server.rs | 2 +- tests/servers/api/environment.rs | 2 +- tests/servers/http/environment.rs | 2 +- 19 files changed, 92 insertions(+), 133 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 072a21a7..c22c3dd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ axum = { version = "0", features = ["macros"] } axum-client-ip = "0" axum-extra = { version = "0", features = ["query"] } axum-server = { version = "0", features = ["tls-rustls"] } -camino = { version = "1.1.6", features = ["serde"] } +camino = { version = "1.1.6", features = ["serde", "serde1"] } chrono = { version = "0", default-features = false, features = ["clock"] } clap = { version = "4", features = ["derive", "env"] } crossbeam-skiplist = "0.1" diff --git a/docs/containers.md b/docs/containers.md index 1a1ea2f0..82c67c26 100644 --- a/docs/containers.md +++ b/docs/containers.md @@ -330,24 +330,23 @@ The storage folder must contain your certificates: ```s storage/tracker/lib/tls - ├── localhost.crt - └── localhost.key + ├── localhost.crt + └── localhost.key +storage/http_api/lib/tls + ├── localhost.crt + └── localhost.key ``` You have not enabled it in your `tracker.toml` file: ```toml +[http_trackers.tsl_config] +ssl_cert_path = "./storage/tracker/lib/tls/localhost.crt" +ssl_key_path = "./storage/tracker/lib/tls/localhost.key" -[[http_trackers]] -# ... -ssl_enabled = true -# ... - -[http_api] -# ... -ssl_enabled = true -# ... - +[http_api.tsl_config] +ssl_cert_path = "./storage/http_api/lib/tls/localhost.crt" +ssl_key_path = "./storage/http_api/lib/tls/localhost.key" ``` > NOTE: you can enable it independently for each HTTP tracker or the API. diff --git a/packages/configuration/Cargo.toml b/packages/configuration/Cargo.toml index bac2132d..53e4e4cf 100644 --- a/packages/configuration/Cargo.toml +++ b/packages/configuration/Cargo.toml @@ -15,7 +15,7 @@ rust-version.workspace = true version.workspace = true [dependencies] -camino = { version = "1.1.6", features = ["serde"] } +camino = { version = "1.1.6", features = ["serde", "serde1"] } derive_more = "0" figment = { version = "0.10.18", features = ["env", "test", "toml"] } serde = { version = "1", features = ["derive"] } diff --git a/packages/configuration/src/lib.rs b/packages/configuration/src/lib.rs index 594a283d..c8c91443 100644 --- a/packages/configuration/src/lib.rs +++ b/packages/configuration/src/lib.rs @@ -13,7 +13,7 @@ use std::sync::Arc; use camino::Utf8PathBuf; use derive_more::Constructor; use serde::{Deserialize, Serialize}; -use serde_with::{serde_as, NoneAsEmptyString}; +use serde_with::serde_as; use thiserror::Error; use torrust_tracker_located_error::{DynError, LocatedError}; @@ -215,24 +215,23 @@ impl From for Error { #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Default)] pub struct TslConfig { /// Path to the SSL certificate file. - #[serde_as(as = "NoneAsEmptyString")] #[serde(default = "TslConfig::default_ssl_cert_path")] - pub ssl_cert_path: Option, + pub ssl_cert_path: Utf8PathBuf, + /// Path to the SSL key file. - #[serde_as(as = "NoneAsEmptyString")] #[serde(default = "TslConfig::default_ssl_key_path")] - pub ssl_key_path: Option, + pub ssl_key_path: Utf8PathBuf, } impl TslConfig { #[allow(clippy::unnecessary_wraps)] - fn default_ssl_cert_path() -> Option { - Some(Utf8PathBuf::new()) + fn default_ssl_cert_path() -> Utf8PathBuf { + Utf8PathBuf::new() } #[allow(clippy::unnecessary_wraps)] - fn default_ssl_key_path() -> Option { - Some(Utf8PathBuf::new()) + fn default_ssl_key_path() -> Utf8PathBuf { + Utf8PathBuf::new() } } diff --git a/packages/configuration/src/v1/http_tracker.rs b/packages/configuration/src/v1/http_tracker.rs index b1fe1437..fed2282a 100644 --- a/packages/configuration/src/v1/http_tracker.rs +++ b/packages/configuration/src/v1/http_tracker.rs @@ -12,19 +12,17 @@ pub struct HttpTracker { /// Weather the HTTP tracker is enabled or not. #[serde(default = "HttpTracker::default_enabled")] pub enabled: bool, + /// The address the tracker will bind to. /// The format is `ip:port`, for example `0.0.0.0:6969`. If you want to /// listen to all interfaces, use `0.0.0.0`. If you want the operating /// system to choose a random port, use port `0`. #[serde(default = "HttpTracker::default_bind_address")] pub bind_address: SocketAddr, - /// Weather the HTTP tracker will use SSL or not. - #[serde(default = "HttpTracker::default_ssl_enabled")] - pub ssl_enabled: bool, - /// TSL config. Only used if `ssl_enabled` is true. - #[serde(flatten)] - #[serde(default = "TslConfig::default")] - pub tsl_config: TslConfig, + + /// TSL config. + #[serde(default = "HttpTracker::default_tsl_config")] + pub tsl_config: Option, } impl Default for HttpTracker { @@ -32,8 +30,7 @@ impl Default for HttpTracker { Self { enabled: Self::default_enabled(), bind_address: Self::default_bind_address(), - ssl_enabled: Self::default_ssl_enabled(), - tsl_config: TslConfig::default(), + tsl_config: Self::default_tsl_config(), } } } @@ -47,7 +44,7 @@ impl HttpTracker { SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 7070) } - fn default_ssl_enabled() -> bool { - false + fn default_tsl_config() -> Option { + None } } diff --git a/packages/configuration/src/v1/mod.rs b/packages/configuration/src/v1/mod.rs index 19499cd4..2caf26d5 100644 --- a/packages/configuration/src/v1/mod.rs +++ b/packages/configuration/src/v1/mod.rs @@ -176,14 +176,16 @@ //! //! ```s //! [[http_trackers]] -//! enabled = true //! ... +//! +//! [http_trackers.tsl_config] //! ssl_cert_path = "./storage/tracker/lib/tls/localhost.crt" //! ssl_key_path = "./storage/tracker/lib/tls/localhost.key" //! //! [http_api] -//! enabled = true //! ... +//! +//! [http_api.tsl_config] //! ssl_cert_path = "./storage/tracker/lib/tls/localhost.crt" //! ssl_key_path = "./storage/tracker/lib/tls/localhost.key" //! ``` @@ -225,16 +227,10 @@ //! [[http_trackers]] //! enabled = false //! bind_address = "0.0.0.0:7070" -//! ssl_enabled = false -//! ssl_cert_path = "" -//! ssl_key_path = "" //! //! [http_api] //! enabled = true //! bind_address = "127.0.0.1:1212" -//! ssl_enabled = false -//! ssl_cert_path = "" -//! ssl_key_path = "" //! //! [http_api.access_tokens] //! admin = "MyAccessToken" @@ -419,16 +415,10 @@ mod tests { [[http_trackers]] enabled = false bind_address = "0.0.0.0:7070" - ssl_enabled = false - ssl_cert_path = "" - ssl_key_path = "" - + [http_api] enabled = true bind_address = "127.0.0.1:1212" - ssl_enabled = false - ssl_cert_path = "" - ssl_key_path = "" [http_api.access_tokens] admin = "MyAccessToken" diff --git a/packages/configuration/src/v1/tracker_api.rs b/packages/configuration/src/v1/tracker_api.rs index c2e3e5ee..42794ad1 100644 --- a/packages/configuration/src/v1/tracker_api.rs +++ b/packages/configuration/src/v1/tracker_api.rs @@ -15,19 +15,18 @@ pub struct HttpApi { /// Weather the HTTP API is enabled or not. #[serde(default = "HttpApi::default_enabled")] pub enabled: bool, + /// The address the tracker will bind to. /// The format is `ip:port`, for example `0.0.0.0:6969`. If you want to /// listen to all interfaces, use `0.0.0.0`. If you want the operating /// system to choose a random port, use port `0`. #[serde(default = "HttpApi::default_bind_address")] pub bind_address: SocketAddr, - /// Weather the HTTP API will use SSL or not. - #[serde(default = "HttpApi::default_ssl_enabled")] - pub ssl_enabled: bool, + /// TSL config. Only used if `ssl_enabled` is true. - #[serde(flatten)] - #[serde(default = "TslConfig::default")] - pub tsl_config: TslConfig, + #[serde(default = "HttpApi::default_tsl_config")] + pub tsl_config: Option, + /// Access tokens for the HTTP API. The key is a label identifying the /// token and the value is the token itself. The token is used to /// authenticate the user. All tokens are valid for all endpoints and have @@ -41,8 +40,7 @@ impl Default for HttpApi { Self { enabled: Self::default_enabled(), bind_address: Self::default_bind_address(), - ssl_enabled: Self::default_ssl_enabled(), - tsl_config: TslConfig::default(), + tsl_config: Self::default_tsl_config(), access_tokens: Self::default_access_tokens(), } } @@ -57,8 +55,9 @@ impl HttpApi { SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1212) } - fn default_ssl_enabled() -> bool { - false + #[allow(clippy::unnecessary_wraps)] + fn default_tsl_config() -> Option { + None } fn default_access_tokens() -> AccessTokens { diff --git a/share/default/config/tracker.container.mysql.toml b/share/default/config/tracker.container.mysql.toml index 75cc57b6..70ee8b50 100644 --- a/share/default/config/tracker.container.mysql.toml +++ b/share/default/config/tracker.container.mysql.toml @@ -3,9 +3,5 @@ driver = "MySQL" path = "mysql://db_user:db_user_secret_password@mysql:3306/torrust_tracker" [[http_trackers]] -ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" -ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" - -[http_api] -ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" -ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" +bind_address = "0.0.0.0:7070" +enabled = true diff --git a/share/default/config/tracker.container.sqlite3.toml b/share/default/config/tracker.container.sqlite3.toml index 433e3612..f7bb6b8b 100644 --- a/share/default/config/tracker.container.sqlite3.toml +++ b/share/default/config/tracker.container.sqlite3.toml @@ -1,10 +1,2 @@ [core.database] path = "/var/lib/torrust/tracker/database/sqlite3.db" - -[[http_trackers]] -ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" -ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" - -[http_api] -ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" -ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" diff --git a/share/default/config/tracker.e2e.container.sqlite3.toml b/share/default/config/tracker.e2e.container.sqlite3.toml index b8adedef..744d267f 100644 --- a/share/default/config/tracker.e2e.container.sqlite3.toml +++ b/share/default/config/tracker.e2e.container.sqlite3.toml @@ -6,12 +6,6 @@ enabled = true [[http_trackers]] enabled = true -ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" -ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" - -[http_api] -ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" -ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" [health_check_api] # Must be bound to wildcard IP to be accessible from outside the container diff --git a/src/bootstrap/jobs/http_tracker.rs b/src/bootstrap/jobs/http_tracker.rs index e9eb6bc1..05bfe234 100644 --- a/src/bootstrap/jobs/http_tracker.rs +++ b/src/bootstrap/jobs/http_tracker.rs @@ -42,7 +42,7 @@ pub async fn start_job( if config.enabled { let socket = config.bind_address; - let tls = make_rust_tls(config.ssl_enabled, &config.tsl_config) + let tls = make_rust_tls(&config.tsl_config) .await .map(|tls| tls.expect("it should have a valid http tracker tls configuration")); diff --git a/src/bootstrap/jobs/mod.rs b/src/bootstrap/jobs/mod.rs index 316e5746..f42a843f 100644 --- a/src/bootstrap/jobs/mod.rs +++ b/src/bootstrap/jobs/mod.rs @@ -20,27 +20,33 @@ pub struct Started { pub address: std::net::SocketAddr, } -pub async fn make_rust_tls(enabled: bool, tsl_config: &TslConfig) -> Option> { - if !enabled { - info!("TLS not enabled"); - return None; - } +pub async fn make_rust_tls(opt_tsl_config: &Option) -> Option> { + match opt_tsl_config { + Some(tsl_config) => { + let cert = tsl_config.ssl_cert_path.clone(); + let key = tsl_config.ssl_key_path.clone(); - if let (Some(cert), Some(key)) = (tsl_config.ssl_cert_path.clone(), tsl_config.ssl_key_path.clone()) { - info!("Using https: cert path: {cert}."); - info!("Using https: key path: {key}."); - - Some( - RustlsConfig::from_pem_file(cert, key) - .await - .map_err(|err| Error::BadTlsConfig { - source: (Arc::new(err) as DynError).into(), - }), - ) - } else { - Some(Err(Error::MissingTlsConfig { - location: Location::caller(), - })) + if !cert.exists() || !key.exists() { + return Some(Err(Error::MissingTlsConfig { + location: Location::caller(), + })); + } + + info!("Using https: cert path: {cert}."); + info!("Using https: key path: {key}."); + + Some( + RustlsConfig::from_pem_file(cert, key) + .await + .map_err(|err| Error::BadTlsConfig { + source: (Arc::new(err) as DynError).into(), + }), + ) + } + None => { + info!("TLS not enabled"); + None + } } } @@ -54,29 +60,23 @@ mod tests { #[tokio::test] async fn it_should_error_on_bad_tls_config() { - let err = make_rust_tls( - true, - &TslConfig { - ssl_cert_path: Some(Utf8PathBuf::from("bad cert path")), - ssl_key_path: Some(Utf8PathBuf::from("bad key path")), - }, - ) + let err = make_rust_tls(&Some(TslConfig { + ssl_cert_path: Utf8PathBuf::from("bad cert path"), + ssl_key_path: Utf8PathBuf::from("bad key path"), + })) .await .expect("tls_was_enabled") .expect_err("bad_cert_and_key_files"); - assert!(matches!(err, Error::BadTlsConfig { source: _ })); + assert!(matches!(err, Error::MissingTlsConfig { location: _ })); } #[tokio::test] async fn it_should_error_on_missing_cert_or_key_paths() { - let err = make_rust_tls( - true, - &TslConfig { - ssl_cert_path: None, - ssl_key_path: None, - }, - ) + let err = make_rust_tls(&Some(TslConfig { + ssl_cert_path: Utf8PathBuf::from(""), + ssl_key_path: Utf8PathBuf::from(""), + })) .await .expect("tls_was_enabled") .expect_err("missing_config"); diff --git a/src/bootstrap/jobs/tracker_apis.rs b/src/bootstrap/jobs/tracker_apis.rs index 3c1f1325..c3b12d7a 100644 --- a/src/bootstrap/jobs/tracker_apis.rs +++ b/src/bootstrap/jobs/tracker_apis.rs @@ -63,7 +63,7 @@ pub async fn start_job( if config.enabled { let bind_to = config.bind_address; - let tls = make_rust_tls(config.ssl_enabled, &config.tsl_config) + let tls = make_rust_tls(&config.tsl_config) .await .map(|tls| tls.expect("it should have a valid tracker api tls configuration")); diff --git a/src/lib.rs b/src/lib.rs index c059f6df..e378594d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,17 +199,11 @@ //! [[http_trackers]] //! bind_address = "0.0.0.0:7070" //! enabled = false -//! ssl_cert_path = "" -//! ssl_enabled = false -//! ssl_key_path = "" -//! +//! //! [http_api] //! bind_address = "127.0.0.1:1212" //! enabled = true -//! ssl_cert_path = "" -//! ssl_enabled = false -//! ssl_key_path = "" -//! +//! //! [http_api.access_tokens] //! admin = "MyAccessToken" //! @@ -261,9 +255,6 @@ //! [http_api] //! enabled = true //! bind_address = "127.0.0.1:1212" -//! ssl_enabled = false -//! ssl_cert_path = "" -//! ssl_key_path = "" //! ``` //! //! By default it's enabled on port `1212`. You also need to add access tokens in the configuration: diff --git a/src/servers/apis/mod.rs b/src/servers/apis/mod.rs index 47d40c65..ab361013 100644 --- a/src/servers/apis/mod.rs +++ b/src/servers/apis/mod.rs @@ -27,7 +27,8 @@ //! [http_api] //! enabled = true //! bind_address = "0.0.0.0:1212" -//! ssl_enabled = false +//! +//! [http_api.tsl_config] //! ssl_cert_path = "./storage/tracker/lib/tls/localhost.crt" //! ssl_key_path = "./storage/tracker/lib/tls/localhost.key" //! @@ -115,7 +116,8 @@ //! [http_api] //! enabled = true //! bind_address = "0.0.0.0:1212" -//! ssl_enabled = true +//! +//! [http_api.tsl_config] //! ssl_cert_path = "./storage/tracker/lib/tls/localhost.crt" //! ssl_key_path = "./storage/tracker/lib/tls/localhost.key" //! diff --git a/src/servers/apis/server.rs b/src/servers/apis/server.rs index 7c5b8983..74dc8969 100644 --- a/src/servers/apis/server.rs +++ b/src/servers/apis/server.rs @@ -280,7 +280,7 @@ mod tests { let bind_to = config.bind_address; - let tls = make_rust_tls(config.ssl_enabled, &config.tsl_config) + let tls = make_rust_tls(&config.tsl_config) .await .map(|tls| tls.expect("tls config failed")); diff --git a/src/servers/http/server.rs b/src/servers/http/server.rs index 5c33fc8f..bbe0c3cc 100644 --- a/src/servers/http/server.rs +++ b/src/servers/http/server.rs @@ -239,7 +239,7 @@ mod tests { let bind_to = config.bind_address; - let tls = make_rust_tls(config.ssl_enabled, &config.tsl_config) + let tls = make_rust_tls(&config.tsl_config) .await .map(|tls| tls.expect("tls config failed")); diff --git a/tests/servers/api/environment.rs b/tests/servers/api/environment.rs index cacde8af..8f84620d 100644 --- a/tests/servers/api/environment.rs +++ b/tests/servers/api/environment.rs @@ -35,7 +35,7 @@ impl Environment { let bind_to = config.bind_address; - let tls = block_on(make_rust_tls(config.ssl_enabled, &config.tsl_config)).map(|tls| tls.expect("tls config failed")); + let tls = block_on(make_rust_tls(&config.tsl_config)).map(|tls| tls.expect("tls config failed")); let server = ApiServer::new(Launcher::new(bind_to, tls)); diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 61837c40..6e80569e 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -33,7 +33,7 @@ impl Environment { let bind_to = config.bind_address; - let tls = block_on(make_rust_tls(config.ssl_enabled, &config.tsl_config)).map(|tls| tls.expect("tls config failed")); + let tls = block_on(make_rust_tls(&config.tsl_config)).map(|tls| tls.expect("tls config failed")); let server = HttpServer::new(Launcher::new(bind_to, tls));