proxy: support presigned (query string auth) SigV4 requests - #256
Open
FredNass wants to merge 1 commit into
Open
proxy: support presigned (query string auth) SigV4 requests#256FredNass wants to merge 1 commit into
FredNass wants to merge 1 commit into
Conversation
FredNass
requested review from
aiivashchenko,
arttor,
fa-at-pulsit and
schucly
as code owners
September 4, 2026 12:56
FredNass
force-pushed
the
proxy-presigned-v4
branch
from
September 7, 2026 08:47
9e381a2 to
6f84d67
Compare
4 tasks
FredNass
force-pushed
the
proxy-presigned-v4
branch
from
September 7, 2026 16:45
6f84d67 to
2e5d334
Compare
4 tasks
The proxy auth middleware only recognized header-based AWS SigV4/SigV2 signatures. A presigned URL carries its SigV4 parameters in the query string (X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, ...) and no Authorization header, so such requests were rejected with 400 CredentialsNotSupported before reaching the storage backend. This broke clients that rely on presigned URLs for downloads/uploads, e.g. web applications that redirect the browser to a presigned URL, aws-sdk presign, or 'rclone link', when pointed at the chorus proxy. Add query-string SigV4 authentication: - s3.ParsePreSignV4 parses the X-Amz-* auth query parameters - doesPresignedSignatureV4Match validates X-Amz-Expires bounds, signing date and expiry, then verifies the signature over the canonical request (all query params except X-Amz-Signature, UNSIGNED-PAYLOAD unless a payload checksum was signed) - after successful validation, the X-Amz-* auth params are stripped from the URL so the request forwarded to the backend carries only the Authorization header computed by the proxy Presigned SigV2 URLs remain unsupported. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Frédéric Nass <frederic.nass@clyso.com>
FredNass
force-pushed
the
proxy-presigned-v4
branch
from
September 8, 2026 11:56
2e5d334 to
321404c
Compare
Contributor
Author
|
@arttor ready for review. ;-) |
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.
Description
The proxy auth middleware only recognizes header-based
Authorizationsignatures (SigV4, and SigV2 when enabled). A presigned URL carries its SigV4 parameters in the query string (X-Amz-Algorithm,X-Amz-Credential,X-Amz-Date,X-Amz-Expires,X-Amz-SignedHeaders,X-Amz-Signature) and noAuthorizationheader, soisReqAuthenticated()falls through to400 CredentialsNotSupportedwithout contacting the backend. Any client relying on presigned URLs (browser-based download flows of S3 gateways and web front-ends,aws s3 presign,rclone link, SDKgenerate_presigned_url) is broken behind the proxy.Changes:
pkg/s3/presign.go:ParsePreSignV4(url.Values)parses the query-string authentication parameters intoPreSignValues(credential scope, date, expires, signed headers, signature), mirroring the existingParseSignV4for theAuthorizationheader.service/proxy/auth/signature_v4_presign.go:isRequestPresignedSignatureV4()detects query-string auth (presence ofX-Amz-Credential, as in MinIO).doesPresignedSignatureV4Match()validatesX-Amz-Expiresbounds (1s..7d), rejects not-yet-valid (15 min skew allowance) and expired requests with the AWS error codes (AuthorizationQueryParametersError,AccessDenied), then verifies the signature over the canonical request — all query parameters exceptX-Amz-Signature,UNSIGNED-PAYLOADunless a payload checksum was signed — reusing the existing SigV4 helpers, so region handling is identical to the header path (the scope region is used as-is, e.g. RGW zonegroup names likedefault).removePresignParams()strips theX-Amz-*auth parameters after successful validation, so the request forwarded to the backend carries a single authentication mechanism: theAuthorizationheader computed by the proxy inpkg/s3client. Non-auth query parameters (response-content-disposition,versionId, ...) are preserved.service/proxy/auth/middleware.go: dispatch presigned requests inisReqAuthenticated(), strip the auth params inWrap()after successful authentication.Presigned SigV2 URLs remain unsupported (out of scope; the SigV2 path still requires the
Authorizationheader).Testing:
service/proxy/auth/signature_v4_presign_test.go: valid presigned GET (including non-AWS region scopedefaultand extraresponse-*query params), wrong secret, unknown access key, expired / not-yet-valid dates, out-of-boundsX-Amz-Expires, dispatch fromisReqAuthenticated,CredentialsNotSupportedpreserved for unauthenticated requests, and auth-param stripping throughWrap().default, unicode/space object keys,response-*params, HEAD,versionId, tampered URL and wrong-secret rejection).Related Issue
Fixes #255
Checklist
Signed-off-byline to certify agreement with the Developer Certificate of Origin (DCO).make testpassingNote: By submitting this PR, you agree to license your contributions under the Apache 2.0 License and follow our Code of Conduct.
🤖 Generated with Claude Code