Repository navigation
refactor(tsa,oidc,tuf)!: accept caller-configured reqwest clients - #249
Merged
Merged
Conversation
Let callers configure timeouts, proxies, TLS roots, the user agent and the TLS provider on their own `reqwest::Client`, instead of each crate growing its own knobs. `reqwest` is re-exported from each crate so a matching client can be built. - `TimestampClientBuilder::with_http_client` replaces its `timeout` and `user_agent` options. - `OAuthClient::with_http_client(config, client)`; `OAuthClient::new` returns `Result`, and its default client (30-second timeout, sigstore-rust user agent) replaces the per-request token timeout, which would otherwise override a caller's client settings. - `HttpRepository::with_http_client`, documented to need timeouts against the slow-retrieval attack. Without a supplied client, each crate keeps its current default timeouts. BREAKING CHANGE: `TimestampClientBuilder::timeout` and `user_agent` are replaced by `with_http_client`; `OAuthClient::new` returns `Result`; reqwest is part of the public API of sigstore-tsa (with `client`), sigstore-oidc and sigstore-tuf (with `fetch`). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Wolf Vollprecht <w.vollprecht@gmail.com>
jku
approved these changes
Sep 25, 2026
| // without them a malicious mirror can hang a refresh indefinitely. The | ||
| // read timeout is per read operation, so large-but-flowing target | ||
| // downloads are unaffected; only a stalled connection trips it. | ||
| let client = reqwest::Client::builder() |
Member
There was a problem hiding this comment.
this should have a default user-agent as well -- but we can leave that for #253
| /// Configure timeouts on it: without them a malicious mirror can hang | ||
| /// a refresh indefinitely (the slow-retrieval attack, TUF spec | ||
| /// §1.5.10). | ||
| pub fn with_http_client(mut self, client: reqwest::Client) -> Self { |
Member
There was a problem hiding this comment.
new() has created a client already when this is called ... but maybe that's not too bad.
Merged
wolfv
added a commit
that referenced
this pull request
Sep 25, 2026
TufConfig::with_http_client passes a reqwest::Client through to the TUF HTTP repository (#249), so trust material fetches use the caller's timeouts, proxies, TLS roots and user agent. reqwest is re-exported with the tuf feature. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Wolf Vollprecht <w.vollprecht@gmail.com>
wolfv
added a commit
that referenced
this pull request
Sep 25, 2026
TufConfig::with_http_client passes a reqwest::Client through to the TUF HTTP repository (#249), so trust material fetches use the caller's timeouts, proxies, TLS roots and user agent. reqwest is re-exported with the tuf feature. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Wolf Vollprecht <w.vollprecht@gmail.com>
wolfv
added a commit
that referenced
this pull request
Sep 26, 2026
TufConfig::with_http_client passes a reqwest::Client through to the TUF HTTP repository (#249), so trust material fetches use the caller's timeouts, proxies, TLS roots and user agent. reqwest is re-exported with the tuf feature. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Wolf Vollprecht <w.vollprecht@gmail.com>
wolfv
added a commit
that referenced
this pull request
Sep 28, 2026
…material (#251) * refactor(rekor)!: typed client API, status errors and injected HTTP clients - Typed client methods: `get_entry_by_uuid(&EntryUuid)`, `get_entry_by_index(LogIndex)` (was `i64`), `search_index` and `search_by_hash` return `Vec<EntryUuid>`, `search_by_hash` takes a `&Sha256Hash`, and `get_public_key` returns a parsed `DerPublicKey` instead of PEM text. - Non-success responses are `Error::Status { status, message }`, so a 409 ("entry already exists") can be told apart from a 5xx; malformed bodies are `InvalidResponse` rather than `Http`. `Error` is `#[non_exhaustive]`, and the unused `Api` and `Base64` variants are removed. - `RekorClientBuilder::with_http_client` and `RekorV2Client::with_http_client` accept a caller-configured `reqwest::Client` (re-exported), replacing `with_timeout` and `new_with_timeout`. `RekorClient::new`, `RekorV2Client::new` and `build` return `Result` instead of panicking. - The duplicated request plumbing is folded into shared helpers. BREAKING CHANGE: the Rekor client methods take and return typed values; `RekorClient::new`, `RekorV2Client::new` and `RekorClientBuilder::build` return `Result`; `with_timeout` and `new_with_timeout` are replaced by `with_http_client`; `Error::Api` is replaced by `Error::Status`. * refactor(rekor)!: typed entry bodies and extensible response types - Replace `RekorEntryBody::from_base64_json(&str, &str, &str)` with `RekorEntryBody::parse(&CanonicalizedBody, KindVersion)` for bundle entries and `from_json(&[u8], kind, version)` for raw bodies. Callers no longer re-encode the canonicalized body to base64 only for it to be decoded again (#199 review). The untagged `Deserialize` derive, which guessed the body type from its shape, is removed. - `LogEntry::log_index` and `RekorInclusionProof::log_index` are `LogIndex`, so out-of-range indices are rejected while parsing. - `LogInfo::tree_i_d` and `InactiveShard::tree_i_d` are renamed `tree_id` (serialized as `treeID`). - `RekorApiVersion`, `RekorV2KeyDetails`, `RekorEntryBody` and the response structs (`LogEntry`, `Verification`, `RekorInclusionProof`, `LogInfo`, `InactiveShard`) are `#[non_exhaustive]`. `RekorApiVersion::major()` and `from_major()` replace hand-written version mapping in sigstore-sign. - `LogEntryResponse` is crate-private. BREAKING CHANGE: `RekorEntryBody::from_base64_json` is replaced by `parse` and `from_json`, and `RekorEntryBody` no longer implements `Deserialize`; log indices are `LogIndex`; `tree_i_d` is `tree_id`; the listed types are `#[non_exhaustive]`; `LogEntryResponse` is no longer public. * refactor(trust-root)!: extensible trust material types and typed errors - Mark `TrustedRoot`, `TransparencyLog`, `CertificateAuthority`, `CertificateTransparencyLog`, `TimestampAuthority`, `PublicKey`, `CertificateSubject`, `CertChain`, `CertificateEntry`, `SigningConfig`, `ServiceEndpoint`, `ServiceConfiguration`, `SigstoreInstance` and `Error` `#[non_exhaustive]`, so new protobuf-specs fields and instances are not breaking changes. - `PublicKey::key_details` is a `PublicKeyDetails` newtype instead of a bare `String`. - `TrustedRoot::fulcio_certs` returns `Vec<DerCertificate>` instead of `rustls_pki_types::CertificateDer`, which is no longer a public dependency (nor, like `base64`, a dependency at all). - Errors: `sigstore_types` errors are wrapped as `Error::Types` instead of being mapped by variant (unknown ones became `InvalidKey`); file reads report `Error::Io` instead of `MissingField` or a JSON error; the unused `Base64` and `MissingField` variants are removed. - `SigningConfig::from_file` takes `impl AsRef<Path>`, like `TrustedRoot::from_file`. - Remove the `ValidityPeriod` alias of `TimeRange`. BREAKING CHANGE: the listed types are `#[non_exhaustive]`; `PublicKey::key_details` is `PublicKeyDetails`; `fulcio_certs` returns `DerCertificate`s; `ValidityPeriod` is removed (use `TimeRange`); `Error` gains `Io` and `Types` and loses `Base64` and `MissingField`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Wolf Vollprecht <w.vollprecht@gmail.com> * refactor(trust-root)!: drop get_ prefixes from signing config lookups Follow the Rust API guidelines. The filtered lists are named for what they return, since plain names would collide with the public fields: get_rekor_urls -> eligible_rekor_urls, get_rekor_url -> rekor_url, and likewise for Fulcio, TSA and OIDC endpoints. BREAKING CHANGE: SigningConfig::get_{rekor,fulcio,tsa,oidc}_url(s) are renamed {rekor,fulcio,tsa,oidc}_url and eligible_{..}_urls. * refactor(trust-root)!: SigstoreInstance as the source of well-known endpoints Well-known TUF URLs and bootstrap roots were separate public constants that every configuration constructor combined by hand. Make the instance the one place that knows them, so a new instance is one enum variant (the enum is `#[non_exhaustive]`). - `SigstoreInstance::tuf_url()` and `tuf_root()` replace the public `DEFAULT_TUF_URL`, `STAGING_TUF_URL`, `GITHUB_TUF_URL` and `*_TUF_ROOT` constants, which are now private. - `SigstoreInstance::embedded_signing_config()` / `embedded_signing_config_json()` sit next to the embedded trusted root (GitHub's instance publishes none). - `TufConfig::for_instance(instance)` backs `production()`, `staging()`, `github()` and `SigstoreInstance::tuf_config()`. - `TufBootstrap` is `#[non_exhaustive]`. The TUF target names (`TRUSTED_ROOT_TARGET`, `SIGNING_CONFIG_TARGET`) remain public. BREAKING CHANGE: the TUF URL and root constants are no longer public; use `SigstoreInstance::tuf_url()` / `tuf_root()`. `TufBootstrap` is `#[non_exhaustive]`. * feat(trust-root): accept a caller-configured reqwest client for TUF TufConfig::with_http_client passes a reqwest::Client through to the TUF HTTP repository (#249), so trust material fetches use the caller's timeouts, proxies, TLS roots and user agent. reqwest is re-exported with the tuf feature. * refactor(rekor)!: remove log info and public key endpoints `RekorClient::get_public_key` fetched the log's verification key from the log itself. Verification must take Rekor keys from the trusted root, so a server-supplied (and cached) key is a way to bypass the trust model rather than a feature. `get_log_info` has no use in signing or verification either; monitoring and diagnostics can query the endpoint directly. - Remove `get_public_key`, `get_log_info` and the `LogInfo` / `InactiveShard` types. - These were the only users of response caching, so the `cache` feature and `RekorClientBuilder::with_cache` / `with_shared_cache` are removed as well. Signed-off-by: Wolf Vollprecht <w.vollprecht@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Applies the decision from #248 to the HTTP clients that aren't blocked by #247: callers pass in their own
reqwest::Clientand configure timeouts, proxies, TLS roots, the user agent and the TLS provider (#220) on it.reqwestbecomes a public dependency and is re-exported from each crate.TimestampClientBuilder::with_http_clientreplaces itstimeout/user_agentoptionsOAuthClient::with_http_client(config, client)OAuthClient::newnow returnsResultHttpRepository::with_http_client, documented to need timeouts against the slow-retrieval attack (TUF §1.5.10)Without a supplied client, each crate keeps its current default timeouts. Rekor's clients get the same shape in the Rekor PR once #247 lands. Plumbing a client through
TufConfigandSigningContextcomes with the trust-root and sign PRs.Validation
cargo clippy --workspace --all-targets --all-features -- -D warningscargo test -p sigstore-tsa -p sigstore-oidc -p sigstore-tuf -p sigstore-trust-root -p sigstore-sign --all-featurescargo check --no-default-featuresfor tsa, oidc and tufSigned-off-by: Wolf Vollprecht w.vollprecht@gmail.com
🤖 Generated with Claude Code