1
0
mirror of https://github.com/actix/examples synced 2025-05-14 08:43:59 +02:00

feat: use rustls best practice for clients

This commit is contained in:
Rob Ede 2025-05-12 03:36:54 +01:00
parent c39ea70fa8
commit dfce64475b
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
7 changed files with 201 additions and 47 deletions

View File

@ -6,14 +6,24 @@ column_width = 100
[[rule]] [[rule]]
include = ["**/Cargo.toml"] include = ["**/Cargo.toml"]
keys = ["dependencies", "*-dependencies"] keys = [
"dependencies",
[rule.formatting] "*-dependencies",
reorder_keys = true "workspace.dependencies",
"workspace.*-dependencies",
"target.*.dependencies",
"target.*.*-dependencies",
]
formatting.reorder_keys = true
[[rule]] [[rule]]
include = ["**/Cargo.toml"] include = ["**/Cargo.toml"]
keys = ["dependencies.*", "*-dependencies.*"] keys = [
"dependencies.*",
[rule.formatting] "*-dependencies.*",
reorder_keys = false "workspace.dependencies.*",
"workspace.*-dependencies.*",
"target.*.dependencies",
"target.*.*-dependencies",
]
formatting.reorder_keys = false

141
Cargo.lock generated
View File

@ -1120,7 +1120,7 @@ dependencies = [
"log", "log",
"mime", "mime",
"rustls 0.23.27", "rustls 0.23.27",
"webpki-roots 0.26.11", "rustls-platform-verifier",
] ]
[[package]] [[package]]
@ -2037,6 +2037,12 @@ dependencies = [
"shlex", "shlex",
] ]
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]] [[package]]
name = "cexpr" name = "cexpr"
version = "0.6.0" version = "0.6.0"
@ -4519,6 +4525,28 @@ dependencies = [
"syn 2.0.101", "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]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.33" version = "0.1.33"
@ -7026,6 +7054,33 @@ dependencies = [
"zeroize", "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]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.101.7" version = "0.101.7"
@ -9458,6 +9513,24 @@ dependencies = [
"wasm-bindgen", "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]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "0.25.4" version = "0.25.4"
@ -9725,6 +9798,15 @@ dependencies = [
"windows-link", "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]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"
@ -9752,6 +9834,21 @@ dependencies = [
"windows-targets 0.52.6", "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]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.48.5" version = "0.48.5"
@ -9799,6 +9896,12 @@ dependencies = [
"windows_x86_64_msvc 0.53.0", "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]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.48.5" version = "0.48.5"
@ -9817,6 +9920,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.48.5" version = "0.48.5"
@ -9835,6 +9944,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.48.5" version = "0.48.5"
@ -9865,6 +9980,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.48.5" version = "0.48.5"
@ -9883,6 +10004,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 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]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.48.5" version = "0.48.5"
@ -9901,6 +10028,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 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]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.48.5" version = "0.48.5"
@ -9919,6 +10052,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 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]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.48.5" version = "0.48.5"

View File

@ -97,13 +97,14 @@ actix-ws = "0.3"
awc = "3.7" awc = "3.7"
chrono = { version = "0.4.30", features = ["serde"] } chrono = { version = "0.4.30", features = ["serde"] }
color-eyre = "0.6"
derive_more = "2" derive_more = "2"
dotenvy = "0.15" dotenvy = "0.15"
env_logger = "0.11" env_logger = "0.11"
eyre = { version = "0.6", default-features = false, features = ["auto-install", "track-caller"] } 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"] } futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
log = "0.4" log = "0.4"
mime = "0.3"
notify = "8" notify = "8"
openssl = { version = "0.10.60", features = ["v110"] } openssl = { version = "0.10.60", features = ["v110"] }
parking_lot = "0.12" parking_lot = "0.12"
@ -114,11 +115,11 @@ reqwest = { version = "0.12", features = ["json", "stream"] }
rustls = "0.23" rustls = "0.23"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
time = "0.3"
temp-env = "0.3" temp-env = "0.3"
time = "0.3"
tokio = { version = "1.24.2", features = ["sync", "io-util"] } tokio = { version = "1.24.2", features = ["sync", "io-util"] }
tokio-util = "0.7.4"
tokio-stream = "0.1.1" tokio-stream = "0.1.1"
tokio-util = "0.7.4"
tracing = "0.1.30" tracing = "0.1.30"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
uuid = { version = "1.6", features = ["v4", "v7", "serde"] } uuid = { version = "1.6", features = ["v4", "v7", "serde"] }

View File

@ -4,11 +4,10 @@ edition.workspace = true
rust-version.workspace = true rust-version.workspace = true
[dependencies] [dependencies]
actix-web.workspace = true actix-web = { workspace = true }
awc = { workspace = true, features = ["rustls-0_23"] } awc = { workspace = true, features = ["rustls-0_23"] }
env_logger = { workspace = true }
env_logger.workspace = true log = { workspace = true }
log.workspace = true mime = { workspace = true }
mime = "0.3" rustls = { workspace = true }
rustls.workspace = true rustls-platform-verifier = "0.5"
webpki-roots = "0.26"

View File

@ -1,14 +1,13 @@
use std::{sync::Arc, time::Instant}; 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 awc::{Client, Connector, http::header};
use rustls::{ClientConfig, RootCertStore};
const MAP_URL: &str = const MAP_URL: &str =
"https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg"; "https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg";
#[get("/")] #[get("/")]
async fn fetch_image(client: Data<Client>) -> HttpResponse { async fn fetch_image(client: ThinData<Client>) -> HttpResponse {
let start = Instant::now(); let start = Instant::now();
let mut res = client.get(MAP_URL).send().await.unwrap(); let mut res = client.get(MAP_URL).send().await.unwrap();
@ -20,13 +19,14 @@ async fn fetch_image(client: Data<Client>) -> HttpResponse {
let payload = res let payload = res
.body() .body()
// expected image is larger than default body limit // expected image is larger than default body limit, set up a higher
.limit(20_000_000) // 20MB // limit of 20 MB
.limit(20_000_000)
.await .await
.unwrap(); .unwrap();
log::info!( log::info!(
"it took {}ms to download image to memory", "It took {}ms to download image to memory",
start.elapsed().as_millis() start.elapsed().as_millis()
); );
@ -41,7 +41,7 @@ async fn main() -> std::io::Result<()> {
let client_tls_config = Arc::new(rustls_config()); 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 || { HttpServer::new(move || {
// create client _inside_ `HttpServer::new` closure to have one per worker thread // create client _inside_ `HttpServer::new` closure to have one per worker thread
@ -53,9 +53,9 @@ async fn main() -> std::io::Result<()> {
.finish(); .finish();
App::new() App::new()
.wrap(middleware::Logger::default()) .app_data(ThinData(client))
.app_data(Data::new(client))
.service(fetch_image) .service(fetch_image)
.wrap(middleware::Logger::default())
}) })
.bind(("127.0.0.1", 8080))? .bind(("127.0.0.1", 8080))?
.workers(2) .workers(2)
@ -63,15 +63,15 @@ async fn main() -> std::io::Result<()> {
.await .await
} }
/// Create simple rustls client config from root certificates. /// Create simple `rustls` client config.
fn rustls_config() -> ClientConfig { fn rustls_config() -> rustls::ClientConfig {
use rustls_platform_verifier::ConfigVerifierExt as _;
rustls::crypto::aws_lc_rs::default_provider() rustls::crypto::aws_lc_rs::default_provider()
.install_default() .install_default()
.unwrap(); .unwrap();
let root_store = RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.to_owned()); // The benefits of the platform verifier are clear; see:
// https://github.com/rustls/rustls-platform-verifier#readme
rustls::ClientConfig::builder() rustls::ClientConfig::with_platform_verifier()
.with_root_certificates(root_store)
.with_no_client_auth()
} }

View File

@ -6,6 +6,6 @@ rust-version.workspace = true
[dependencies] [dependencies]
actix-tls = { workspace = true, features = ["rustls-0_23"] } actix-tls = { workspace = true, features = ["rustls-0_23"] }
actix-web = { workspace = true, features = ["rustls-0_23"] } actix-web = { workspace = true, features = ["rustls-0_23"] }
env_logger.workspace = true env_logger = { workspace = true }
log.workspace = true log = { workspace = true }
rustls.workspace = true rustls = { workspace = true }

View File

@ -5,7 +5,8 @@ use std::{any::Any, net::SocketAddr, sync::Arc};
use actix_tls::accept::rustls_0_23::TlsStream; use actix_tls::accept::rustls_0_23::TlsStream;
use actix_web::{ 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 log::info;
use rustls::{ use rustls::{
@ -101,13 +102,17 @@ async fn main() -> std::io::Result<()> {
.with_single_cert(cert_chain, key_der) .with_single_cert(cert_chain, key_der)
.unwrap(); .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))) HttpServer::new(|| {
.on_connect(get_client_cert) App::new()
.bind(("localhost", 8080))? .default_service(web::to(route_whoami))
.bind_rustls_0_23(("localhost", 8443), config)? .wrap(Logger::default())
.workers(1) })
.run() .on_connect(get_client_cert)
.await .bind(("localhost", 8080))?
.bind_rustls_0_23(("localhost", 8443), config)?
.workers(2)
.run()
.await
} }