From dfce64475be541c427a121a59972b0e55ba93112 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 12 May 2025 03:36:54 +0100 Subject: [PATCH] feat: use rustls best practice for clients --- .taplo.toml | 26 +++-- Cargo.lock | 141 ++++++++++++++++++++++- Cargo.toml | 7 +- https-tls/awc-https/Cargo.toml | 13 +-- https-tls/awc-https/src/main.rs | 32 ++--- https-tls/rustls-client-cert/Cargo.toml | 6 +- https-tls/rustls-client-cert/src/main.rs | 23 ++-- 7 files changed, 201 insertions(+), 47 deletions(-) diff --git a/.taplo.toml b/.taplo.toml index e82aef42..6da4c7f1 100644 --- a/.taplo.toml +++ b/.taplo.toml @@ -6,14 +6,24 @@ column_width = 100 [[rule]] include = ["**/Cargo.toml"] -keys = ["dependencies", "*-dependencies"] - -[rule.formatting] -reorder_keys = true +keys = [ + "dependencies", + "*-dependencies", + "workspace.dependencies", + "workspace.*-dependencies", + "target.*.dependencies", + "target.*.*-dependencies", +] +formatting.reorder_keys = true [[rule]] include = ["**/Cargo.toml"] -keys = ["dependencies.*", "*-dependencies.*"] - -[rule.formatting] -reorder_keys = false +keys = [ + "dependencies.*", + "*-dependencies.*", + "workspace.dependencies.*", + "workspace.*-dependencies.*", + "target.*.dependencies", + "target.*.*-dependencies", +] +formatting.reorder_keys = false diff --git a/Cargo.lock b/Cargo.lock index e79b2ac5..7d5cab90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1120,7 +1120,7 @@ dependencies = [ "log", "mime", "rustls 0.23.27", - "webpki-roots 0.26.11", + "rustls-platform-verifier", ] [[package]] @@ -2037,6 +2037,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -4519,6 +4525,28 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.33" @@ -7026,6 +7054,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" +dependencies = [ + "core-foundation 0.10.0", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.27", + "rustls-native-certs 0.8.1", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.3", + "security-framework 3.2.0", + "security-framework-sys", + "webpki-root-certs 0.26.11", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -9458,6 +9513,24 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" +dependencies = [ + "webpki-root-certs 1.0.0", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a83f7e1a9f8712695c03eabe9ed3fbca0feff0152f33f12593e5a6303cb1a4" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -9725,6 +9798,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -9752,6 +9834,21 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -9799,6 +9896,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -9817,6 +9920,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -9835,6 +9944,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -9865,6 +9980,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -9883,6 +10004,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -9901,6 +10028,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -9919,6 +10052,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" diff --git a/Cargo.toml b/Cargo.toml index 999dbc81..48a54e0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,13 +97,14 @@ actix-ws = "0.3" awc = "3.7" chrono = { version = "0.4.30", features = ["serde"] } +color-eyre = "0.6" derive_more = "2" dotenvy = "0.15" env_logger = "0.11" eyre = { version = "0.6", default-features = false, features = ["auto-install", "track-caller"] } -color-eyre = "0.6" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } log = "0.4" +mime = "0.3" notify = "8" openssl = { version = "0.10.60", features = ["v110"] } parking_lot = "0.12" @@ -114,11 +115,11 @@ reqwest = { version = "0.12", features = ["json", "stream"] } rustls = "0.23" serde = { version = "1", features = ["derive"] } serde_json = "1" -time = "0.3" temp-env = "0.3" +time = "0.3" tokio = { version = "1.24.2", features = ["sync", "io-util"] } -tokio-util = "0.7.4" tokio-stream = "0.1.1" +tokio-util = "0.7.4" tracing = "0.1.30" tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } uuid = { version = "1.6", features = ["v4", "v7", "serde"] } diff --git a/https-tls/awc-https/Cargo.toml b/https-tls/awc-https/Cargo.toml index e0aa72af..55b664ce 100644 --- a/https-tls/awc-https/Cargo.toml +++ b/https-tls/awc-https/Cargo.toml @@ -4,11 +4,10 @@ edition.workspace = true rust-version.workspace = true [dependencies] -actix-web.workspace = true +actix-web = { workspace = true } awc = { workspace = true, features = ["rustls-0_23"] } - -env_logger.workspace = true -log.workspace = true -mime = "0.3" -rustls.workspace = true -webpki-roots = "0.26" +env_logger = { workspace = true } +log = { workspace = true } +mime = { workspace = true } +rustls = { workspace = true } +rustls-platform-verifier = "0.5" diff --git a/https-tls/awc-https/src/main.rs b/https-tls/awc-https/src/main.rs index 4f23aa42..8a92941b 100644 --- a/https-tls/awc-https/src/main.rs +++ b/https-tls/awc-https/src/main.rs @@ -1,14 +1,13 @@ use std::{sync::Arc, time::Instant}; -use actix_web::{App, HttpResponse, HttpServer, get, middleware, web::Data}; +use actix_web::{App, HttpResponse, HttpServer, get, middleware, web::ThinData}; use awc::{Client, Connector, http::header}; -use rustls::{ClientConfig, RootCertStore}; const MAP_URL: &str = "https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg"; #[get("/")] -async fn fetch_image(client: Data) -> HttpResponse { +async fn fetch_image(client: ThinData) -> HttpResponse { let start = Instant::now(); let mut res = client.get(MAP_URL).send().await.unwrap(); @@ -20,13 +19,14 @@ async fn fetch_image(client: Data) -> HttpResponse { let payload = res .body() - // expected image is larger than default body limit - .limit(20_000_000) // 20MB + // expected image is larger than default body limit, set up a higher + // limit of 20 MB + .limit(20_000_000) .await .unwrap(); log::info!( - "it took {}ms to download image to memory", + "It took {}ms to download image to memory", start.elapsed().as_millis() ); @@ -41,7 +41,7 @@ async fn main() -> std::io::Result<()> { let client_tls_config = Arc::new(rustls_config()); - log::info!("starting HTTP server at http://localhost:8080"); + log::info!("Starting HTTP server at http://localhost:8080"); HttpServer::new(move || { // create client _inside_ `HttpServer::new` closure to have one per worker thread @@ -53,9 +53,9 @@ async fn main() -> std::io::Result<()> { .finish(); App::new() - .wrap(middleware::Logger::default()) - .app_data(Data::new(client)) + .app_data(ThinData(client)) .service(fetch_image) + .wrap(middleware::Logger::default()) }) .bind(("127.0.0.1", 8080))? .workers(2) @@ -63,15 +63,15 @@ async fn main() -> std::io::Result<()> { .await } -/// Create simple rustls client config from root certificates. -fn rustls_config() -> ClientConfig { +/// Create simple `rustls` client config. +fn rustls_config() -> rustls::ClientConfig { + use rustls_platform_verifier::ConfigVerifierExt as _; + rustls::crypto::aws_lc_rs::default_provider() .install_default() .unwrap(); - let root_store = RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.to_owned()); - - rustls::ClientConfig::builder() - .with_root_certificates(root_store) - .with_no_client_auth() + // The benefits of the platform verifier are clear; see: + // https://github.com/rustls/rustls-platform-verifier#readme + rustls::ClientConfig::with_platform_verifier() } diff --git a/https-tls/rustls-client-cert/Cargo.toml b/https-tls/rustls-client-cert/Cargo.toml index ea10dd2f..21569130 100644 --- a/https-tls/rustls-client-cert/Cargo.toml +++ b/https-tls/rustls-client-cert/Cargo.toml @@ -6,6 +6,6 @@ rust-version.workspace = true [dependencies] actix-tls = { workspace = true, features = ["rustls-0_23"] } actix-web = { workspace = true, features = ["rustls-0_23"] } -env_logger.workspace = true -log.workspace = true -rustls.workspace = true +env_logger = { workspace = true } +log = { workspace = true } +rustls = { workspace = true } diff --git a/https-tls/rustls-client-cert/src/main.rs b/https-tls/rustls-client-cert/src/main.rs index 67bd55e5..0fca7716 100644 --- a/https-tls/rustls-client-cert/src/main.rs +++ b/https-tls/rustls-client-cert/src/main.rs @@ -5,7 +5,8 @@ use std::{any::Any, net::SocketAddr, sync::Arc}; use actix_tls::accept::rustls_0_23::TlsStream; use actix_web::{ - App, HttpRequest, HttpResponse, HttpServer, Responder, dev::Extensions, rt::net::TcpStream, web, + App, HttpRequest, HttpResponse, HttpServer, Responder, dev::Extensions, middleware::Logger, + rt::net::TcpStream, web, }; use log::info; use rustls::{ @@ -101,13 +102,17 @@ async fn main() -> std::io::Result<()> { .with_single_cert(cert_chain, key_der) .unwrap(); - log::info!("starting HTTP server at http://localhost:8080 and https://localhost:8443"); + log::info!("Starting HTTP server at http://localhost:8080 and https://localhost:8443"); - HttpServer::new(|| App::new().default_service(web::to(route_whoami))) - .on_connect(get_client_cert) - .bind(("localhost", 8080))? - .bind_rustls_0_23(("localhost", 8443), config)? - .workers(1) - .run() - .await + HttpServer::new(|| { + App::new() + .default_service(web::to(route_whoami)) + .wrap(Logger::default()) + }) + .on_connect(get_client_cert) + .bind(("localhost", 8080))? + .bind_rustls_0_23(("localhost", 8443), config)? + .workers(2) + .run() + .await }