feat(auth): implement opt-in SigV4 cryptographic verification#390
Merged
vieiralucas merged 1 commit intomainfrom Apr 14, 2026
Merged
feat(auth): implement opt-in SigV4 cryptographic verification#390vieiralucas merged 1 commit intomainfrom
vieiralucas merged 1 commit intomainfrom
Conversation
Adds the real SigV4 verifier behind the --verify-sigv4 flag plumbed in
batch 1. Off by default; when enabled, requests with invalid signatures
are rejected before reaching service handlers with protocol-correct
AWS errors (SignatureDoesNotMatch, InvalidClientTokenId,
RequestTimeTooSkewed, IncompleteSignature).
- New ParsedSigV4 + parse_sigv4_header/parse_sigv4_presigned that
extract the full credential scope, signed headers, signature, and
X-Amz-Date from Authorization headers and presigned URL query params.
- New verify() that:
1. checks clock skew (±15 min, matches AWS)
2. reconstructs the canonical request (double-encoded path for
non-S3, single for S3, sorted query string dropping
X-Amz-Signature for presigned, lowercased+sorted headers)
3. derives the signing key via the four-step HMAC chain
4. compares in constant time via subtle::ConstantTimeEq
- Respects X-Amz-Content-Sha256 when present (supports S3's
UNSIGNED-PAYLOAD + STREAMING-* values pass-through).
- New CredentialResolver trait in fakecloud-core::auth and
IamCredentialResolver impl in fakecloud-iam, keeping the
dependency edge pointing core -> iam.
- Dispatch integration: when config.verify_sigv4 is on and the caller
isn't the test/test root bypass, resolve secret, verify, map errors.
- Bootstrapping via test/test root bypass still works end-to-end so
`FAKECLOUD_VERIFY_SIGV4=true` is usable from a fresh server.
- Added aws-sigv4-supporting deps: hmac, hex, subtle (chrono +
percent-encoding + sha2 already workspace-wide).
Tests:
- 12 unit tests in fakecloud-aws::sigv4 covering parse, canonical URI
(S3 vs non-S3), canonical query, signing-key determinism, clock
skew, round-trip verification, and tampered-body rejection.
- 2 unit tests in fakecloud-iam::credential_resolver covering the IAM
state adapter.
- 6 end-to-end tests in sigv4_verification.rs that spawn a real
fakecloud process with FAKECLOUD_VERIFY_SIGV4=true, drive real
signed requests through aws-sdk-rust clients, and cover:
* valid signed request from a newly-created IAM user
* unknown AKID -> InvalidClientTokenId
* wrong secret -> SignatureDoesNotMatch
* root bypass (test/test) always accepted
* off-by-default regression guard
* STS temp credentials from AssumeRole verify successfully
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
Batch 3 of 9 for the opt-in SigV4 + IAM enforcement work. Ships the real SigV4 verifier behind the
--verify-sigv4/FAKECLOUD_VERIFY_SIGV4flag plumbed in batch 1. Off by default — existing workflows see zero behavior change.What's verified
When enabled, every incoming request is checked cryptographically before reaching the service handler:
X-Amz-Signaturefor presigned URLsX-Amz-Content-Sha256when present (supports S3'sUNSIGNED-PAYLOAD+STREAMING-*pass-through), otherwisesha256(body)subtle::ConstantTimeEqError mapping
Verification failures are returned as protocol-correct AWS errors before business logic runs:
SignatureDoesNotMatchInvalidClientTokenIdRequestTimeTooSkewedIncompleteSignatureRoot bypass
The reserved
test*AKID prefix (shipped in batch 1) short-circuits verification sotest/testcredentials always work — community convention matching LocalStack and Floci. A startuptracing::warn!already fires when the flag is on to prevent false-positive "my policies work" results from unsigned test clients.Architecture
CredentialResolvertrait infakecloud_core::authand concreteIamCredentialResolverinfakecloud_iam— the dependency edge stays core → iam.DispatchConfiggainscredential_resolver: Option<Arc<dyn CredentialResolver>>.ResolvedCredential.account_idis sourced from the credential itself, not from global config, priming the shape Feature proposal: multi-account isolation within a single fakecloud instance #381 (multi-account isolation) will need.Decisions
aws-sigv4crate. The AWS crate pulls inaws-smithy-runtime-api+aws-credential-typestransitively, which is a heavy dependency for a ~400-line well-specified algorithm. The round-trip E2E test below signs requests via the real aws-sdk-rust and verifies them through our implementation — that's the ground-truth correctness check.UNSIGNED-PAYLOAD/STREAMING-*markers are part of the signature, so echoing them into the canonical request matches what the client signed.testtesttest...,fakefakefake...) to avoid GitHub's push-protection secret scanning.Test plan
cargo test -p fakecloud-aws sigv4::— 12 unit tests (parse header, parse presigned, canonical URI S3 vs non-S3, canonical query, signing key determinism, clock skew, round-trip verification, tampered body rejection)cargo test -p fakecloud-iam credential_resolver— 2 unit tests for the IAM state adaptercargo test -p fakecloud-core— 43 tests, no regressionscargo test -p fakecloud-e2e --test sigv4_verification— 6 end-to-end tests that spawn a real fakecloud withFAKECLOUD_VERIFY_SIGV4=true, drive signed requests throughaws-sdk-rust, and cover:InvalidClientTokenIdSignatureDoesNotMatchtest/test) always acceptedcargo test -p fakecloud-e2e --test iam— 57 tests, no regressionscargo test -p fakecloud-conformance— no regressionscargo clippy --workspace --all-targets -- -D warningscleancargo fmt --checkcleanSummary by cubic
Adds opt-in SigV4 cryptographic verification behind
--verify-sigv4/FAKECLOUD_VERIFY_SIGV4. Off by default; when enabled, bad signatures are rejected with AWS-accurate errors before any handler runs.New Features
fakecloud-aws(verify,parse_sigv4_header,parse_sigv4_presigned).X-Amz-Signaturefor presigned); lowercased/sorted headers; payload hash trustsX-Amz-Content-Sha256(supports S3UNSIGNED-PAYLOAD/STREAMING-*).SignatureDoesNotMatch,InvalidClientTokenId,RequestTimeTooSkewed,IncompleteSignature.CredentialResolvertrait infakecloud-core;IamCredentialResolverinfakecloud-iam. Dispatch resolves the secret and verifies per request.test*AKID root bypass remains.Migration
--verify-sigv4or setFAKECLOUD_VERIFY_SIGV4=true.test/teststill works via the bypass (for local bootstrapping).Written for commit f4ff1d9. Summary will update on new commits.