From d807a374b891014433535cb26fe66dea5a16d463 Mon Sep 17 00:00:00 2001 From: Aaron Marten Date: Fri, 3 Apr 2026 11:40:59 -0700 Subject: [PATCH] feat(crypto): add support for crypto-native-tls feature and update reqwest dependencies --- .github/workflows/rust-ci.yml | 3 ++ rust/otap-dataflow/Cargo.toml | 3 +- .../crates/contrib-nodes/Cargo.toml | 2 +- rust/otap-dataflow/crates/otap/Cargo.toml | 9 ++--- rust/otap-dataflow/crates/otap/src/crypto.rs | 34 ++++++++++++++----- .../otap/src/otlp_http/client_settings.rs | 24 +++++++++++-- rust/otap-dataflow/src/main.rs | 15 ++++++++ 7 files changed, 73 insertions(+), 17 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index fa6191359f..c8c335a755 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -376,6 +376,9 @@ jobs: - name: cargo check benchmarks --no-default-features run: cargo check -p benchmarks --benches --no-default-features working-directory: ./rust/${{ matrix.folder }} + - name: cargo check --no-default-features --features crypto-native-tls + run: cargo check --no-default-features --features crypto-native-tls --workspace + working-directory: ./rust/${{ matrix.folder }} # Required matrix combinations for test_and_coverage: otap-dataflow on ubuntu and windows test_and_coverage_required: diff --git a/rust/otap-dataflow/Cargo.toml b/rust/otap-dataflow/Cargo.toml index e919ce0a5a..3dfda43923 100644 --- a/rust/otap-dataflow/Cargo.toml +++ b/rust/otap-dataflow/Cargo.toml @@ -207,7 +207,7 @@ cpu-time = "1.0.0" azure_core = {version = "0.33.0", default-features = false } azure_identity = {version = "0.33.0", default-features = false } flate2 = "1.1.5" -reqwest = { version = "0.13.1", features = ["rustls-no-provider", "json", "query", "http2", "stream"] } +reqwest = { version = "0.13.1", default-features = false, features = ["charset", "http2", "json", "query", "stream", "system-proxy"] } time = "0.3.44" wiremock = "0.6.5" anyhow = "1.0.98" @@ -255,6 +255,7 @@ experimental-tls = ["otap-df-otap/experimental-tls", "otap-df-core-nodes/experim crypto-ring = ["otap-df-otap/crypto-ring"] crypto-aws-lc = ["otap-df-otap/crypto-aws-lc"] crypto-openssl = ["otap-df-otap/crypto-openssl"] +crypto-native-tls = ["otap-df-otap/crypto-native-tls"] # Contrib exporters (opt-in) - now in contrib-nodes contrib-exporters = ["otap-df-contrib-nodes/contrib-exporters"] diff --git a/rust/otap-dataflow/crates/contrib-nodes/Cargo.toml b/rust/otap-dataflow/crates/contrib-nodes/Cargo.toml index 7b0030906c..2482bf359b 100644 --- a/rust/otap-dataflow/crates/contrib-nodes/Cargo.toml +++ b/rust/otap-dataflow/crates/contrib-nodes/Cargo.toml @@ -49,7 +49,7 @@ http = { workspace = true, optional = true } itoa = { workspace = true, optional = true } rand = { workspace = true, optional = true } ryu = { workspace = true, optional = true } -reqwest = { workspace = true, optional = true, features = ["rustls-no-provider"] } +reqwest = { workspace = true, optional = true } sysinfo = { workspace = true, optional = true } urlencoding = { workspace = true, optional = true } diff --git a/rust/otap-dataflow/crates/otap/Cargo.toml b/rust/otap-dataflow/crates/otap/Cargo.toml index 1edc7fe337..e2517bbfcf 100644 --- a/rust/otap-dataflow/crates/otap/Cargo.toml +++ b/rust/otap-dataflow/crates/otap/Cargo.toml @@ -63,7 +63,7 @@ tokio-util = { workspace = true, features = ["rt"] } async-stream.workspace = true humantime.workspace = true rand.workspace = true -reqwest = { workspace = true, features = ["http2", "rustls-no-provider", "stream"] } +reqwest = { workspace = true, features = ["http2", "stream"] } tower = { workspace = true } hyper-util = { workspace = true } hyper = { workspace = true } @@ -93,9 +93,10 @@ byte-unit.workspace = true [features] test-utils = ["dep:rustls", "rustls/ring", "otap-df-pdata/testing"] experimental-tls = ["dep:rustls", "dep:rustls-pki-types", "dep:tokio-rustls", "dep:rustls-native-certs", "dep:arc-swap", "dep:notify", "tonic/tls-native-roots"] -crypto-ring = ["dep:rustls", "rustls/ring", "tokio-rustls?/ring"] -crypto-aws-lc = ["dep:rustls", "rustls/aws_lc_rs", "tokio-rustls?/aws-lc-rs"] -crypto-openssl = ["dep:rustls", "dep:rustls-openssl", "tonic/tls-native-roots"] +crypto-ring = ["dep:rustls", "rustls/ring", "tokio-rustls?/ring", "reqwest/rustls-no-provider"] +crypto-aws-lc = ["dep:rustls", "rustls/aws_lc_rs", "tokio-rustls?/aws-lc-rs", "reqwest/rustls-no-provider"] +crypto-openssl = ["dep:rustls", "dep:rustls-openssl", "tonic/tls-native-roots", "reqwest/rustls-no-provider"] +crypto-native-tls = ["reqwest/native-tls"] azure = ["object_store/azure", "object_store/cloud", "dep:azure_identity", "dep:azure_core"] aws = ["object_store/aws", "object_store/cloud"] diff --git a/rust/otap-dataflow/crates/otap/src/crypto.rs b/rust/otap-dataflow/crates/otap/src/crypto.rs index 56e6b8ee00..ed00411461 100644 --- a/rust/otap-dataflow/crates/otap/src/crypto.rs +++ b/rust/otap-dataflow/crates/otap/src/crypto.rs @@ -7,11 +7,12 @@ //! [`CryptoProvider`](rustls::crypto::CryptoProvider) based on compile-time //! feature flags. Exactly one of the `crypto-*` features must be enabled: //! -//! | Feature | Backend | Use-case | -//! |------------------|------------------|------------------------------------| -//! | `crypto-ring` | `ring` | Default, backward-compatible | -//! | `crypto-aws-lc` | `aws-lc-rs` | AWS environments, broader algos | -//! | `crypto-openssl` | `rustls-openssl` | Regulated / FIPS environments | +//! | Feature | Backend | Use-case | +//! |---------------------|------------------|----------------------------------------| +//! | `crypto-ring` | `ring` | Default, backward-compatible | +//! | `crypto-aws-lc` | `aws-lc-rs` | AWS environments, broader algos | +//! | `crypto-openssl` | `rustls-openssl` | Regulated / FIPS environments | +//! | `crypto-native-tls` | `native-tls` | Platform-native TLS (SChannel/OpenSSL) | /// Installs the selected rustls `CryptoProvider` as the process-wide default. /// @@ -51,16 +52,29 @@ pub fn install_crypto_provider() -> Result<(), String> { .map_err(|_| "crypto provider already installed (openssl)".to_string())?; } + #[cfg(all( + feature = "crypto-native-tls", + not(feature = "crypto-ring"), + not(feature = "crypto-aws-lc"), + not(feature = "crypto-openssl") + ))] + { + // native-tls uses the platform's TLS stack (SChannel/OpenSSL/Security.framework) + // and does not require a rustls CryptoProvider. + } + #[cfg(not(any( feature = "crypto-ring", feature = "crypto-aws-lc", - feature = "crypto-openssl" + feature = "crypto-openssl", + feature = "crypto-native-tls" )))] { otap_df_telemetry::otel_warn!( "crypto.no_provider", message = "no crypto-* feature enabled: TLS operations will fail at runtime. \ - Enable exactly one of: crypto-ring, crypto-aws-lc, crypto-openssl" + Enable exactly one of: crypto-ring, crypto-aws-lc, crypto-openssl, \ + crypto-native-tls" ); } @@ -79,7 +93,8 @@ pub fn ensure_crypto_provider() { #[cfg(any( feature = "crypto-ring", feature = "crypto-aws-lc", - feature = "crypto-openssl" + feature = "crypto-openssl", + feature = "crypto-native-tls" ))] { let _ = install_crypto_provider(); @@ -88,7 +103,8 @@ pub fn ensure_crypto_provider() { #[cfg(not(any( feature = "crypto-ring", feature = "crypto-aws-lc", - feature = "crypto-openssl" + feature = "crypto-openssl", + feature = "crypto-native-tls" )))] { let _ = rustls::crypto::ring::default_provider().install_default(); diff --git a/rust/otap-dataflow/crates/otap/src/otlp_http/client_settings.rs b/rust/otap-dataflow/crates/otap/src/otlp_http/client_settings.rs index 1e69564d2a..0d55e33643 100644 --- a/rust/otap-dataflow/crates/otap/src/otlp_http/client_settings.rs +++ b/rust/otap-dataflow/crates/otap/src/otlp_http/client_settings.rs @@ -66,8 +66,28 @@ impl HttpClientSettings { /// Returns a configured client-builder pub async fn client_builder(&self) -> Result { - let mut client_builder = ClientBuilder::new() - .use_rustls_tls() + let mut client_builder = ClientBuilder::new(); + + // Select the TLS backend based on the active crypto feature. + #[cfg(any( + feature = "crypto-ring", + feature = "crypto-aws-lc", + feature = "crypto-openssl" + ))] + { + client_builder = client_builder.use_rustls_tls(); + } + #[cfg(all( + feature = "crypto-native-tls", + not(feature = "crypto-ring"), + not(feature = "crypto-aws-lc"), + not(feature = "crypto-openssl") + ))] + { + client_builder = client_builder.use_native_tls(); + } + + client_builder = client_builder .connect_timeout(self.connect_timeout) .tcp_nodelay(self.tcp_nodelay) .connector_layer(ConcurrencyLimitLayer::new( diff --git a/rust/otap-dataflow/src/main.rs b/rust/otap-dataflow/src/main.rs index 29582365e8..9dc50c3218 100644 --- a/rust/otap-dataflow/src/main.rs +++ b/rust/otap-dataflow/src/main.rs @@ -71,6 +71,21 @@ compile_error!( "Features `crypto-aws-lc` and `crypto-openssl` are mutually exclusive. \ Use --no-default-features to disable the default crypto provider, then enable exactly one." ); +#[cfg(all( + feature = "crypto-native-tls", + any( + feature = "crypto-ring", + feature = "crypto-aws-lc", + feature = "crypto-openssl" + ), + not(any(test, doc)), + not(clippy) +))] +compile_error!( + "Feature `crypto-native-tls` is mutually exclusive with `crypto-ring`, `crypto-aws-lc`, \ + and `crypto-openssl`. Use --no-default-features to disable the default crypto provider, \ + then enable exactly one." +); #[cfg(feature = "mimalloc")] use mimalloc::MiMalloc;