From ffe5678438473d3b4b4b86fd49236a63e8035a77 Mon Sep 17 00:00:00 2001 From: dongresource Date: Sun, 17 Nov 2024 21:56:23 +0100 Subject: [PATCH 1/2] Misc changes to defaults * Listen for HTTP connections on port 8080 by default * Disable HTTPS by default * Disable rank endpoint placeholders by default * Change line endings in config.toml to Unix-style * Hoist built-in config default to top of main.rs * Send newline at the end of version endpoint text * Update .gitignore for cargo-vet --- .gitignore | 1 + config.toml | 42 +++++++++++++++++++++--------------------- src/main.rs | 10 +++++----- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index a92072a..c23159e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.db *.pem secret +supply-chain/ diff --git a/config.toml b/config.toml index 54e4af8..c66210d 100644 --- a/config.toml +++ b/config.toml @@ -1,21 +1,21 @@ -[core] -db_path = "../OpenFusion/database.db" -port = 80 - -[tls] -cert_path = "cert.pem" # app-level TLS only -key_path = "key.pem" # app-level TLS only -port = 443 - -[rankinfo] -route = "/getranks" -placeholders = true - -[auth] -route = "/auth" -secret_path = "secret" -valid_secs = 604_800 # one week - -[cookie] -route = "/cookie" -valid_secs = 60 +[core] +db_path = "../OpenFusion/database.db" +port = 8080 + +# [tls] +# cert_path = "cert.pem" # app-level TLS only +# key_path = "key.pem" # app-level TLS only +# port = 443 + +[rankinfo] +route = "/getranks" +placeholders = false + +[auth] +route = "/auth" +secret_path = "secret" +valid_secs = 604_800 # one week + +[cookie] +route = "/cookie" +valid_secs = 60 diff --git a/src/main.rs b/src/main.rs index cdc6c4d..396a5b7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,10 @@ mod rankinfo; mod statics; mod util; +const DEFAULT_HTTP_PORT: u16 = 8080; +const DEFAULT_HTTPS_PORT: u16 = 443; +const CONFIG_PATH: &str = "config.toml"; + #[derive(Deserialize, Clone)] struct CoreConfig { db_path: String, @@ -41,7 +45,6 @@ struct Config { } impl Config { fn load() -> Self { - const CONFIG_PATH: &str = "config.toml"; let config = std::fs::read_to_string(CONFIG_PATH).expect("Failed to open config file"); toml::from_str(&config).expect("Failed to parse config file") } @@ -115,7 +118,6 @@ async fn main() { const BIND_IP: [u8; 4] = [127, 0, 0, 1]; async fn init_http(routes: Router>, config: &Config, state: AppState) { - const DEFAULT_HTTP_PORT: u16 = 80; let addr = SocketAddr::from((BIND_IP, config.core.port.unwrap_or(DEFAULT_HTTP_PORT))); let app = routes.with_state(Arc::new(state)); @@ -126,8 +128,6 @@ async fn init_http(routes: Router>, config: &Config, state: AppSta } async fn init_https(routes: Router>, config: &Config, mut state: AppState) { - const DEFAULT_HTTPS_PORT: u16 = 443; - state.is_tls = true; let app = routes.with_state(Arc::new(state)); @@ -172,7 +172,7 @@ async fn init_https(routes: Router>, config: &Config, mut state: A async fn get_info(State(state): State>) -> String { format!( - "OFAPI v{}\ntls: {:?}", + "OFAPI v{}\ntls: {:?}\n", env!("CARGO_PKG_VERSION"), state.is_tls ) From b318e888af7cef3602210da39d692d27fbb787e0 Mon Sep 17 00:00:00 2001 From: dongresource Date: Tue, 19 Nov 2024 04:36:55 +0100 Subject: [PATCH 2/2] Handle all endpoints on the same port when not using app-terminated TLS --- Cargo.toml | 2 +- config.toml | 9 ++-- src/auth.rs | 2 - src/cookie.rs | 2 - src/main.rs | 112 +++++++++++++++++++++++++++++--------------------- 5 files changed, 72 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cdf787d..c36d36c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,4 +20,4 @@ toml = "0.8.19" tower-http = { version = "0.5.2", features = ["fs"] } [features] -tls = ["dep:axum-server", "dep:rustls"] +app-tls = ["dep:axum-server", "dep:rustls"] diff --git a/config.toml b/config.toml index c66210d..3751d2f 100644 --- a/config.toml +++ b/config.toml @@ -2,10 +2,11 @@ db_path = "../OpenFusion/database.db" port = 8080 -# [tls] -# cert_path = "cert.pem" # app-level TLS only -# key_path = "key.pem" # app-level TLS only -# port = 443 +# App-terminated TLS, as opposed to proxy-terminated TLS. +[app_tls] +cert_path = "cert.pem" +key_path = "key.pem" +port = 443 [rankinfo] route = "/getranks" diff --git a/src/auth.rs b/src/auth.rs index ff139dd..3a0465f 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -148,7 +148,6 @@ async fn do_auth( State(app): State>, Json(req): Json, ) -> Result { - assert!(app.is_tls); let db = app.db.lock().await; let account_id = check_credentials(&db, &req.username, &req.password)?; let valid_secs = app.config.auth.as_ref().unwrap().valid_secs; @@ -187,7 +186,6 @@ async fn do_check( State(app): State>, headers: HeaderMap, ) -> Result { - assert!(app.is_tls); let Ok(account_id) = util::validate_authed_request(&headers) else { return Err((StatusCode::UNAUTHORIZED, "Bad token".to_string())); }; diff --git a/src/cookie.rs b/src/cookie.rs index 80ef133..03cd0c2 100644 --- a/src/cookie.rs +++ b/src/cookie.rs @@ -70,8 +70,6 @@ async fn get_cookie( State(app): State>, headers: HeaderMap, ) -> Result, (StatusCode, String)> { - assert!(app.is_tls); - let db = app.db.lock().await; let account_id = match util::validate_authed_request(&headers) { Ok(id) => id, diff --git a/src/main.rs b/src/main.rs index 396a5b7..66e6297 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use simplelog::{ColorChoice, LevelFilter, TermLogger, TerminalMode}; use sqlite::Connection; use tokio::sync::Mutex; -#[cfg(feature = "tls")] +#[cfg(feature = "app-tls")] use {axum_server::tls_rustls::RustlsConfig, rustls::crypto::ring}; mod auth; @@ -18,9 +18,11 @@ mod statics; mod util; const DEFAULT_HTTP_PORT: u16 = 8080; -const DEFAULT_HTTPS_PORT: u16 = 443; const CONFIG_PATH: &str = "config.toml"; +#[cfg(feature = "app-tls")] +const DEFAULT_HTTPS_PORT: u16 = 443; + #[derive(Deserialize, Clone)] struct CoreConfig { db_path: String, @@ -38,7 +40,7 @@ struct TlsConfig { #[derive(Deserialize, Clone)] struct Config { core: CoreConfig, - tls: Option, + app_tls: Option, rankinfo: Option, auth: Option, cookie: Option, @@ -54,7 +56,6 @@ impl Config { struct AppState { db: Arc>, rng: Arc, - is_tls: bool, config: Config, } impl AppState { @@ -67,10 +68,19 @@ impl AppState { Self { db: Arc::new(Mutex::new(conn)), rng: Arc::new(SystemRandom::new()), - is_tls: false, config: config.clone(), } } + + fn is_using_app_tls(self: &Self) -> bool { + #[cfg(not(feature = "app-tls"))] + { + return false; + } + + #[allow(unreachable_code)] + self.config.app_tls.is_some() + } } #[tokio::main] @@ -99,20 +109,44 @@ async fn main() { routes = rankinfo::register(routes, rankinfo_config); } - // register HTTPS-only endpoints - let mut routes_tls = Router::new().merge(routes.clone()); + // register secure endpoints + let mut routes_secure = Router::new(); if let Some(ref auth_config) = config.auth { - routes_tls = auth::register(routes_tls, auth_config, &state.rng); + routes_secure = auth::register(routes_secure, auth_config, &state.rng); } if let Some(ref cookie_config) = config.cookie { - routes_tls = cookie::register(routes_tls, cookie_config); + routes_secure = cookie::register(routes_secure, cookie_config); + } + + #[cfg(not(feature = "app-tls"))] + { + warn!("OFAPI was not compiled with the `app-tls` feature. Encryption should be done at the proxy level!"); + + let routes = Router::new().merge(routes).merge(routes_secure); + let http = init_http(routes, &config, state.clone()); + let _ = tokio::join!(http); } - // init both protocols - // N.B. these listen concurrently, but NOT in parallel (see tokio::join!) - let http = init_http(routes, &config, state.clone()); - let https = init_https(routes_tls, &config, state); - let _ = tokio::join!(http, https); + #[cfg(feature = "app-tls")] + { + info!("Using application-level TLS termination."); + + // init secure endpoints on a separate port + // N.B. these listen concurrently, but NOT in parallel (see tokio::join!) + + if state.is_using_app_tls() { + let routes_secure = Router::new().merge(routes.clone()).merge(routes_secure); + let http = init_http(routes, &config, state.clone()); + let https = init_https(routes_secure, &config, state); + let _ = tokio::join!(http, https); + } else { + warn!("Application-level TLS termination disabled. Encryption should be done at the proxy level!"); + + let routes = Router::new().merge(routes).merge(routes_secure); + let http = init_http(routes, &config, state.clone()); + let _ = tokio::join!(http); + } + } } const BIND_IP: [u8; 4] = [127, 0, 0, 1]; @@ -127,53 +161,39 @@ async fn init_http(routes: Router>, config: &Config, state: AppSta axum::serve(listener, app).await.unwrap(); } -async fn init_https(routes: Router>, config: &Config, mut state: AppState) { - state.is_tls = true; +#[cfg(feature = "app-tls")] +async fn init_https(routes: Router>, config: &Config, state: AppState) { let app = routes.with_state(Arc::new(state)); - let Some(ref tls_config) = config.tls else { + let Some(ref tls_config) = config.app_tls else { warn!("Missing or malformed TLS config. HTTPS disabled"); return; }; let addr = SocketAddr::from((BIND_IP, tls_config.port.unwrap_or(DEFAULT_HTTPS_PORT))); - #[cfg(not(feature = "tls"))] - { - warn!("TLS APIs enabled but OFAPI was not compiled with the `tls` feature. Encryption should be done at the proxy level!"); - } - info!("HTTPS listening on {}", addr); - #[cfg(feature = "tls")] - { - ring::default_provider().install_default().unwrap(); - let rustls_cfg = - match RustlsConfig::from_pem_file(&tls_config.cert_path, &tls_config.key_path).await { - Err(e) => { - warn!("Failed to activate TLS ({}); HTTPS disabled", e); - return; - } - Ok(cfg) => cfg, - }; - - axum_server::bind_rustls(addr, rustls_cfg) - .serve(app.into_make_service()) - .await - .unwrap(); - } - - #[cfg(not(feature = "tls"))] - { - let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); - axum::serve(listener, app).await.unwrap(); - } + ring::default_provider().install_default().unwrap(); + let rustls_cfg = + match RustlsConfig::from_pem_file(&tls_config.cert_path, &tls_config.key_path).await { + Err(e) => { + warn!("Failed to activate TLS ({}); HTTPS disabled", e); + return; + } + Ok(cfg) => cfg, + }; + + axum_server::bind_rustls(addr, rustls_cfg) + .serve(app.into_make_service()) + .await + .unwrap(); } async fn get_info(State(state): State>) -> String { format!( "OFAPI v{}\ntls: {:?}\n", env!("CARGO_PKG_VERSION"), - state.is_tls + state.is_using_app_tls() ) }