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).
This commit is contained in:
Chris Lu
2026-09-06 22:05:40 -07:00
committed by GitHub
parent 8537d5bc08
commit 3225d2b0ce
5 changed files with 42 additions and 0 deletions
+2
View File
@@ -6556,11 +6556,13 @@ dependencies = [
"lance-table", "lance-table",
"prometheus", "prometheus",
"reqwest 0.12.28", "reqwest 0.12.28",
"rustls",
"seaweed-worker-core", "seaweed-worker-core",
"seaweed-worker-sort", "seaweed-worker-sort",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
"tonic",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
] ]
+2
View File
@@ -35,6 +35,7 @@ anyhow.workspace = true
async-trait.workspace = true async-trait.workspace = true
clap = { version = "4", features = ["derive", "env"] } clap = { version = "4", features = ["derive", "env"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
rustls = "0.23"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
tokio.workspace = true tokio.workspace = true
@@ -43,6 +44,7 @@ tracing-subscriber.workspace = true
[dev-dependencies] [dev-dependencies]
tokio = { workspace = true } tokio = { workspace = true }
tonic.workspace = true
arrow-array = "58" arrow-array = "58"
arrow-schema = "58" arrow-schema = "58"
arrow-cast = "58" arrow-cast = "58"
+1
View File
@@ -10,5 +10,6 @@ pub mod dataset;
pub mod jobs; pub mod jobs;
pub mod metrics; pub mod metrics;
pub mod preview; pub mod preview;
pub mod tls;
pub use jobs::handlers; pub use jobs::handlers;
+2
View File
@@ -113,6 +113,8 @@ fn metrics_address(ip: &str, port: u16) -> Result<SocketAddr> {
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
weed_lance_worker::tls::install_default_crypto_provider();
tracing_subscriber::fmt() tracing_subscriber::fmt()
.with_env_filter( .with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env() tracing_subscriber::EnvFilter::try_from_default_env()
+35
View File
@@ -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"));
}
}