cosmos: add configurable TLS backend, enforced on reqwest#4649
Conversation
85db841 to
478a388
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds a supported, forward-looking mechanism for asserting the TLS backend used by the Cosmos DB driver's officially-supported reqwest transport. Since the driver intentionally does not expose direct transport access, customers previously had no supported way to pin a TLS backend. The change introduces a TlsBackend enum (single Rustls variant, which is the default), surfaces it as a builder-only ConnectionPoolOptions::tls_backend option, and enforces it on the reqwest::ClientBuilder via tls_backend_rustls(). Because there's a single variant that is also the default, no customer configuration is required today; the value is forward-looking (supports future backends and, per #4616, handing the backend to a user-provided HttpClientFactory).
Changes:
- New
#[non_exhaustive]TlsBackendenum in the driver, re-exported throughazure_data_cosmos. - New
tls_backendfield/getter/with_tls_backendbuilder onConnectionPoolOptions, defaulting toRustls, builder-only (not env-configurable). - Enforcement on the reqwest builder via
tls_backend_rustls(), cfg-gated on therustlsfeature, with added unit tests and CHANGELOG entries.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
sdk/cosmos/azure_data_cosmos_driver/src/options/policies.rs |
Adds the TlsBackend enum with Rustls as the #[default] variant. |
sdk/cosmos/azure_data_cosmos_driver/src/options/mod.rs |
Re-exports TlsBackend from policies. |
sdk/cosmos/azure_data_cosmos/src/options/mod.rs |
Re-exports TlsBackend from the driver into the SDK surface. |
sdk/cosmos/azure_data_cosmos_driver/src/options/connection_pool.rs |
Adds the tls_backend field, getter, builder setter, default wiring, and tests. |
sdk/cosmos/azure_data_cosmos_driver/src/driver/transport/http_client_factory.rs |
Enforces the selected backend on the reqwest builder (cfg-gated) and adds a build test. |
sdk/cosmos/azure_data_cosmos_driver/CHANGELOG.md |
Documents the new feature under the unreleased 0.6.0 Features Added section. |
sdk/cosmos/azure_data_cosmos/CHANGELOG.md |
Documents the re-exported feature under the unreleased 0.37.0 Features Added section. |
I verified the key risk areas:
reqwest::ClientBuilder::tls_backend_rustls()genuinely exists in reqwest (locked at 0.13.3), gated on reqwest's internal__rustlsfeature. The driver'srustlsfeature enablesreqwest/rustls, so the#[cfg(feature = "rustls")]gate on the call correctly matches method availability, and thenot(rustls)path compiles by leaving the builder unchanged.- The
CosmosOptionsderive macro (inenv_onlymode) tolerates the newtls_backendfield having no#[option]attribute — it emitstls_backend: Nonein the generatedfrom_env_vars, consistent with the builder-only design. ConnectionPoolOptionsis only ever constructed viabuild(), so the added field doesn't break any struct-literal construction.- CHANGELOG entries are placed under the existing
Features Addedheaders in the unreleased sections, and the re-export is mirrored from the driver intoazure_data_cosmosas required.
I did not find any objective issues to comment on.
The driver does not expose the HTTP transport, so customers had no supported way to assert a specific TLS backend on the reqwest transport. - Add a `TlsBackend` enum (single variant `TlsBackend::Rustls`, the default) to the driver and re-export it from the SDK. - Add a `tls_backend` option to `ConnectionPoolOptions` with a `with_tls_backend` setter and `tls_backend` getter, defaulting to `Rustls` (builder-only; not environment-configurable). - Flow the selection into `DefaultHttpClientFactory` and enforce it by calling `reqwest::ClientBuilder::tls_backend_rustls()`. The configuration surface (getter, setter, the stored field, and the factory enforcement) is gated on the `rustls` feature. With a single variant there is no honest value the getter could report in a non-rustls build, so rather than have it misreport `Rustls` while the wire uses native-tls, the surface simply does not compile in there. The `TlsBackend` type stays defined and exported in every configuration for API stability. This is additive and changes no behavior for the default (rustls) build, where reqwest already negotiates rustls. It only has an effect in builds that compile in multiple reqwest TLS backends (e.g. `rustls` plus `native_tls`, absent reqwest's `http3` feature), where reqwest would otherwise default to native-tls and the driver now pins rustls instead. Because there is one variant and it is the default, no customer configuration is required today; this is the supported mechanism to add backends later and to hand the selected backend to a user-provided HttpClientFactory once that lands. Fixes Azure#4641. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
478a388 to
cfb6fb3
Compare
Main replaced the compile-time �llow_invalid_certificates feature with a runtime CosmosRuntime certificate-validation option (#4649) and moved FeedScope from the query module to eed (#4512). Update the AAD test client builder to configure ServerCertificateValidation::RequiredUnlessEmulator via CosmosRuntime instead of the removed cfg gate, and fix the FeedScope import. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Problem
The driver does not expose direct access to its HTTP transport (and won't, in a supported fashion). As a result, customers have no supported way to assert a specific TLS backend on the officially-supported
reqwesttransport.Change
Introduces a supported, forward-looking mechanism to select and enforce the TLS backend.
TlsBackendenum —#[non_exhaustive], one variantTlsBackend::Rustls(the#[default]). Added toazure_data_cosmos_driverand re-exported fromazure_data_cosmos.ConnectionPoolOptions::tls_backend— new option withConnectionPoolOptionsBuilder::with_tls_backendand atls_backend()getter, defaulting toRustls. Builder-only (intentionally not environment-configurable).DefaultHttpClientFactory::buildselects the backend and callsreqwest::ClientBuilder::tls_backend_rustls(). The call is cfg-gated on therustlsfeature because that reqwest method only exists when reqwest's rustls backend is compiled in; under a different TLS feature the reqwest default applies.Because there is a single variant and it is the default, no customer configuration is required today. The value is forward-looking: it lets us add new backends in a supported way, and (once #4616 lands) hand the selected backend to a user-provided
HttpClientFactory.Files
options/policies.rs— newTlsBackendenum.options/mod.rs(driver) andoptions/mod.rs(SDK) — export / re-exportTlsBackend.options/connection_pool.rs—tls_backendfield, builder field,with_tls_backend, getter, default wiring; extended option tests.driver/transport/http_client_factory.rs— enforce the backend on the reqwest builder; factory build test.CHANGELOG.md(driver0.6.0, SDK0.37.0) — Features Added entries.Testing & coverage
Unit (added):
connection_pool_options_builder_defaults— defaulttls_backend()isRustls.connection_pool_options_builder_custom_values—with_tls_backend()round-trips through the builder.default_factory_builds_client_with_default_tls_backend(reqwest-gated) — builds a realreqwest::Clientwith the default backend, exercisingtls_backend_rustls()and assertingbuild()succeeds.Suites / static checks (green): 1878 driver lib unit tests;
cargo clippy --all-features --all-targets;cargo doc;cargo fmt --check; cSpell. Compile verified for both therustlsand thenot(rustls)(reqwest+native_tls) feature paths — the main risk surface for the cfg-gated call.Integration testing: No dedicated integration test is added, by design.
Rustlsis the only variant and the default, and the default feature set already used reqwest-over-rustls — so behavior is unchanged and the existing emulator/recorded integration suites already exercise the rustls transport path end-to-end. A bespoke test could not assert more, because reqwest exposes no API to introspect which TLS backend negotiated a connection; the added factory test already proves the client builds and runs with the enforced backend.Fixes #4641.