From 3225d2b0cece220e5bdec1ba542acb2dc06e3093 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sun, 6 Sep 2026 22:05:40 -0700 Subject: [PATCH] rust worker: install rustls CryptoProvider to fix TLS panic (#11194) (#11196) * rust worker: add install_default_crypto_provider helper lance's aws backend pulls aws-lc-rs and reqwest's rustls-tls pulls ring, so rustls 0.23 cannot auto-select a CryptoProvider and tonic's client TLS panics on first use. Add install_default_crypto_provider, pinning the default to aws-lc-rs, mirroring the Rust volume server's helper of the same name. Includes a regression test that builds a TLS channel and panics without the install in this crate, where both providers link. * rust worker: install the crypto provider at startup Call install_default_crypto_provider before any TLS use, the way the Rust volume server does in its main. Without this a worker started with --tls-ca/--tls-cert/--tls-key panics on the first admin dial (#11194). --- seaweed-worker/Cargo.lock | 2 ++ seaweed-worker/crates/lance/Cargo.toml | 2 ++ seaweed-worker/crates/lance/src/lib.rs | 1 + seaweed-worker/crates/lance/src/main.rs | 2 ++ seaweed-worker/crates/lance/src/tls.rs | 35 +++++++++++++++++++++++++ 5 files changed, 42 insertions(+) create mode 100644 seaweed-worker/crates/lance/src/tls.rs diff --git a/seaweed-worker/Cargo.lock b/seaweed-worker/Cargo.lock index b9dec6abe..ce3a56e18 100644 --- a/seaweed-worker/Cargo.lock +++ b/seaweed-worker/Cargo.lock @@ -6556,11 +6556,13 @@ dependencies = [ "lance-table", "prometheus", "reqwest 0.12.28", + "rustls", "seaweed-worker-core", "seaweed-worker-sort", "serde", "serde_json", "tokio", + "tonic", "tracing", "tracing-subscriber", ] diff --git a/seaweed-worker/crates/lance/Cargo.toml b/seaweed-worker/crates/lance/Cargo.toml index 4caa80bc4..962a2b7ac 100644 --- a/seaweed-worker/crates/lance/Cargo.toml +++ b/seaweed-worker/crates/lance/Cargo.toml @@ -35,6 +35,7 @@ anyhow.workspace = true async-trait.workspace = true clap = { version = "4", features = ["derive", "env"] } reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } +rustls = "0.23" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio.workspace = true @@ -43,6 +44,7 @@ tracing-subscriber.workspace = true [dev-dependencies] tokio = { workspace = true } +tonic.workspace = true arrow-array = "58" arrow-schema = "58" arrow-cast = "58" diff --git a/seaweed-worker/crates/lance/src/lib.rs b/seaweed-worker/crates/lance/src/lib.rs index be5da0f7b..69455e2aa 100644 --- a/seaweed-worker/crates/lance/src/lib.rs +++ b/seaweed-worker/crates/lance/src/lib.rs @@ -10,5 +10,6 @@ pub mod dataset; pub mod jobs; pub mod metrics; pub mod preview; +pub mod tls; pub use jobs::handlers; diff --git a/seaweed-worker/crates/lance/src/main.rs b/seaweed-worker/crates/lance/src/main.rs index a87a4b13d..1ff6db40a 100644 --- a/seaweed-worker/crates/lance/src/main.rs +++ b/seaweed-worker/crates/lance/src/main.rs @@ -113,6 +113,8 @@ fn metrics_address(ip: &str, port: u16) -> Result { #[tokio::main] async fn main() -> Result<()> { + weed_lance_worker::tls::install_default_crypto_provider(); + tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env() diff --git a/seaweed-worker/crates/lance/src/tls.rs b/seaweed-worker/crates/lance/src/tls.rs new file mode 100644 index 000000000..d2d37770c --- /dev/null +++ b/seaweed-worker/crates/lance/src/tls.rs @@ -0,0 +1,35 @@ +use rustls::crypto::aws_lc_rs; + +// aws-lc-rs and ring both get linked transitively (lance's aws backend pulls +// aws-lc-rs, reqwest's rustls-tls pulls ring), so rustls can't auto-select a +// provider and tonic's client TLS panics on first use. Pin the default to +// aws-lc-rs, matching the Rust volume server. Idempotent. +pub fn install_default_crypto_provider() { + let _ = aws_lc_rs::default_provider().install_default(); +} + +#[cfg(test)] +mod tests { + use tonic::transport::{Certificate, Channel, ClientTlsConfig, Identity}; + + use super::install_default_crypto_provider; + + const TEST_CERT_PEM: &str = "-----BEGIN CERTIFICATE-----\nMIIBPDCB76ADAgECAhRuRPQgeAu43BT/M7EfAWSdapVdYDAFBgMrZXAwFDESMBAG\nA1UEAwwJbG9jYWxob3N0MB4XDTI2MDcwNTE2MTUyOVoXDTM2MDcwMjE2MTUyOVow\nFDESMBAGA1UEAwwJbG9jYWxob3N0MCowBQYDK2VwAyEAr/3bNIFI+8V32oCiY6y+\nXRFmZpdNQ2g//VtRkT+nQg+jUzBRMB0GA1UdDgQWBBTsy9tLf1zPiXCQfgci6zNi\ndEzRSjAfBgNVHSMEGDAWgBTsy9tLf1zPiXCQfgci6zNidEzRSjAPBgNVHRMBAf8E\nBTADAQH/MAUGAytlcANBAIvsdw0IbvOBBkb9cd7BfMJfIP9pQQrAL03pCRWJFnFh\nSysaLVgFXI4T078IiaM874oO+iB+5vNbWEpc7CkGow4=\n-----END CERTIFICATE-----\n"; + const TEST_KEY_PEM: &str = "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIHbyn71Kk+Y7KT3sBctit7uZpErpoH6qDbFj6P8qGaZH\n-----END PRIVATE KEY-----\n"; + + // Without install_default_crypto_provider this panics in the lance crate, + // where both aws-lc-rs and ring are linked. Mirrors the volume server's + // test_build_grpc_endpoint_with_tls_resolves_crypto_provider. + #[tokio::test] + async fn tls_channel_builds_after_crypto_provider_installed() { + install_default_crypto_provider(); + let config = ClientTlsConfig::new() + .ca_certificate(Certificate::from_pem(TEST_CERT_PEM)) + .identity(Identity::from_pem(TEST_CERT_PEM, TEST_KEY_PEM)); + let endpoint = Channel::from_shared("https://127.0.0.1:9") + .unwrap() + .tls_config(config) + .unwrap(); + assert_eq!(endpoint.uri().scheme_str(), Some("https")); + } +}