Skip to content

Separate TLS transport features from the crypto provider choice - #151

Merged
adriangb merged 2 commits into
mainfrom
rustls-provider-features
Sep 13, 2026
Merged

adriangb merged 2 commits into
mainfrom
rustls-provider-features

Conversation

@adriangb

@adriangb adriangb commented Sep 11, 2026 •

Copy link
Copy Markdown
Member

Transport features and the choice of rustls CryptoProvider are now separate, so applications can either ignore the question entirely or pick a provider themselves. This follows up on #150.

gRPC export over https is currently broken

Before this PR, exporting over gRPC to an https endpoint fails for everyone:

transport error <- Connecting to HTTPS without TLS enabled

tonic configures TLS for an https URI only in Endpoint::new, and none of its public constructors reach it: Channel::builder, Endpoint::from_shared, every TryFrom and FromStr all route to new_uri, which leaves tls: None. So the exporter never enabled TLS, whatever the TLS features said. This PR sets it explicitly, and adds tonic/tls-native-roots for the trust anchors that needs. Verified against tonic 0.14.6 by connecting to a real https endpoint: it fails as above beforehand and connects afterwards.

Features

Feature Purpose
export-grpc, export-http-protobuf, export-http-json select a transport; no crypto provider
tls-aws-lc (default) use aws-lc-rs when the application has not installed a provider

An installed provider always wins, because tonic and reqwest both prefer one over their own fallback. The SDK never installs a process-wide provider itself, since that would break an application's own install_default().

// ring, OpenSSL, SymCrypt, a FIPS build of aws-lc-rs, ...
rustls::crypto::ring::default_provider().install_default().unwrap();

With default features off there is no fallback, and building an exporter returns the new ConfigureError::CryptoProviderRequired instead of letting reqwest panic. logfire-client gets the same split and BuilderError::CryptoProviderRequired.

aws-lc-rs is also the default provider of rustls 0.23 and reqwest 0.13, so the default here is the option least likely to collide with the rest of an application's graph. Note that export-http-protobuf already pulled in aws-lc-rs through reqwest before this PR, so default builds gain nothing new.

FIPS

FIPS needs no feature of its own: enable rustls's fips feature, which switches aws-lc-rs to its FIPS module, and install rustls::crypto::default_fips_provider(). A fips feature here would force cargo clippy --all-features and cargo llvm-cov --all-features to build the FIPS module in CI, which needs a heavier toolchain.

Breaking changes

  • Applications using default-features = false with an export feature must now either add tls-aws-lc or install a provider before configuring Logfire.
  • The two new error variants are source-breaking for any downstream exhaustive match, whatever features are enabled. ConfigureError was already #[non_exhaustive]; BuilderError is now marked the same way, so future variants do not repeat this.

Tests and CI

  • grpc_tls_tests::https_endpoints_have_tls_configured connects to a listener that accepts and never replies: with TLS configured the attempt times out, without it tonic fails immediately. Confirmed it fails when the fix is mutated away, rather than passing by construction.
  • test_crypto_provider in both crates asserts the error without a provider and success once one is installed.
  • CI adds the no-provider configuration (build plus both tests) and a cargo tree check that neither aws-lc-rs nor ring is compiled without tls-aws-lc.

Locally: cargo test --workspace --all-features, --no-default-features, clippy, rustdoc and doctests all pass.

The documented ring-only recipe was also run as written in a separate crate: building an exporter reports CryptoProviderRequired before a provider is installed and succeeds afterwards, and cargo tree -e normal contains ring with no aws-lc-rs.

`export-grpc` and `export-http-*` now select a transport only, and the new
`tls-aws-lc` feature (on by default) supplies aws-lc-rs as the rustls
`CryptoProvider` for whichever of them are enabled. This matches the default
provider of both `rustls` and `reqwest`, and stops the SDK from compiling two
providers into applications which already use one.

An application which installs a provider before configuring Logfire keeps
using it, since `tonic` and `reqwest` both prefer an installed provider. That
is how to export using `ring`, a FIPS build of aws-lc-rs, or any other
provider. Disabling default features leaves no built-in provider at all, and
building an exporter then reports `CryptoProviderRequired` rather than letting
`reqwest` panic.

Also configure TLS explicitly for https gRPC endpoints. `tonic` only does so
in `Endpoint::new`, which none of its public constructors reach, so exporting
over gRPC to an https endpoint failed with "Connecting to HTTPS without TLS
enabled". `tonic/tls-native-roots` supplies the trust anchors it needs.
@codecov-commenter

codecov-commenter commented Sep 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 64.06250% with 23 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
logfire/src/exporters.rs 62.29% 2 Missing and 21 partials ⚠️

📢 Thoughts on this report? Let us know!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The TLS documentation is incomplete, and the stated breaking-change scope omits the new exhaustive-enum break.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Separates transport features from rustls provider selection and fixes TLS configuration for gRPC HTTPS exports.

Changes:

  • Adds explicit gRPC TLS setup and provider validation.
  • Introduces opt-in/default tls-aws-lc features.
  • Adds provider tests and no-provider CI coverage.
File summaries
File Description
.github/workflows/main.yml Adds no-provider build and test checks.
logfire/Cargo.toml Separates transport and provider features.
logfire/src/exporters.rs Configures gRPC TLS and validates providers.
logfire/src/lib.rs Documents TLS setup and its error.
logfire/tests/test_crypto_provider.rs Tests exporter provider requirements.
logfire-client/Cargo.toml Adds separate provider selection.
logfire-client/src/builder.rs Reports missing provider errors.
logfire-client/tests/test_crypto_provider.rs Tests client provider requirements.
Review details
  • Files reviewed: 8/8 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread logfire-client/src/builder.rs Resolved
Comment thread logfire/src/lib.rs Resolved
Both from review feedback. Adding a variant to `BuilderError` breaks
downstream exhaustive matches whatever features are enabled, so mark it
`#[non_exhaustive]` as `ConfigureError` already is.

The documented no-default-features setup also needs a direct `rustls`
dependency to choose a provider, with `rustls`'s own default features
disabled, since those include aws-lc-rs.
}

/// Install a provider, for test configurations which have no built-in one.
fn install_crypto_provider() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a little suspect? Is there another way we can do this

@cetra3 cetra3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, can we test compiling with different feature flags to make sure that we can still compile?

@adriangb

Copy link
Copy Markdown
Member Author

Added a features job running cargo hack check --workspace --feature-powerset --no-dev-deps, so all 40 feature combinations get compiled on their own (41s locally with a warm cache).

@adriangb
adriangb merged commit 1917f47 into main Sep 13, 2026
8 checks passed
@adriangb
adriangb deleted the rustls-provider-features branch September 13, 2026 14:02
@adriangb adriangb mentioned this pull request Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants