Repository navigation
feat(auth): verify signatures against the original request path - #1006
Open
renepardon wants to merge 1 commit into
Open
renepardon wants to merge 1 commit into
renepardon wants to merge 1 commit into
Conversation
Add the opt-in request extension `auth::SignedUriPath`. Servers that route on a rewritten path (for example after stripping a deployment path prefix) insert the path the client sent and signed; s3s then uses it for SigV4 and SigV2 header and presigned verification while routing keeps using the request URI. Without the extension behaviour is unchanged.
renepardon
marked this pull request as ready for review
October 19, 2026 16:32
This branch has not been deployed
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
Servers built on s3s cannot be deployed behind a reverse proxy under a path prefix (for example
https://host/tools/rustfs/api/bucket/key). SigV4/SigV2 sign the request path the client sent, and s3s uses the samereq.uri.path()for both routing and signature verification. A server that strips the prefix before callingS3Servicebreaks every signature. A server that does not strip it routes/tools/rustfs/api/bucket/keyto buckettools.This PR adds an opt-in request extension,
s3s::auth::SignedUriPath, holding the path exactly as the client sent and signed it. When it is present, s3s uses it for every path-signing input:raw_uri_pathand the decoded canonical URI are derived from it)raw_uri_pathinstead ofreq_uri.path())Routing (
classify_request_path) keeps usingreq.uri, and POST Object policy signing is unaffected because it signs no path. Without the extension, behaviour is byte-identical to today (map_or(req.uri.path(), ...)). The extension is meant to be set only by trusted server code from static configuration, never from request headers, which the doc comment states. Streaming (aws-chunked) chunk signatures chain from the seed signature and therefore inherit the signed path.Related issues
Downstream use cases:
rustfs/rustfs#2433 (serving several RustFS instances under path prefixes on one host).
rustfs/rustfs#1069 (Does rustfs support serving under a subpath (e.g., https://xxx.com/rustfs) with configurable basePath?)
rustfs/rustfs#2948 (helm support for subpath domain)
rustfs/rustfs#1427 (console login api with subpath or subrouter support)
Tests
New integration test
crates/s3s/tests/signed_uri_path.rs, run for SigV4 header, SigV4 presigned, SigV2 header and SigV2 presigned. For each scheme it checks:/prefix/bkt/k, dispatched as/bkt/kwith the extension: 200, handler sees bucketbkt, keykSignatureDoesNotMatch, handler not called/other/bkt/k,/prefix/bkt/k/,/bkt/k): 403SignatureDoesNotMatchChecks run on top of current
main:cargo fmt --all --checkcargo clippy --workspace --all-features --all-targets(clean)cargo test -p s3s --all-features --test signed_uri_path(5 passed)cargo test -p s3s --all-features --lib(1048 passed)The change was also exercised end to end in RustFS (aws-sdk-s3 and aws-cli, header auth, multipart, presigned GET/PUT, prefix tampering in both directions rejected with 403) against a local k3s deployment.