diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000000..43cddbbf63d Binary files /dev/null and b/.DS_Store differ diff --git a/.changelog/f63b26b19e2e4330b4240f38088453ea.json b/.changelog/f63b26b19e2e4330b4240f38088453ea.json new file mode 100644 index 00000000000..ef398bf401e --- /dev/null +++ b/.changelog/f63b26b19e2e4330b4240f38088453ea.json @@ -0,0 +1,8 @@ +{ + "id": "f63b26b1-9e2e-4330-b424-0f38088453ea", + "type": "bugfix", + "description": "Improve handling of whitespace (or lack thereof) in sigv4 GetSignedRequestSignature.", + "modules": [ + "." + ] +} \ No newline at end of file diff --git a/aws/signer/v4/middleware.go b/aws/signer/v4/middleware.go index a10ee510afe..8a46220a37b 100644 --- a/aws/signer/v4/middleware.go +++ b/aws/signer/v4/middleware.go @@ -372,8 +372,9 @@ func GetSignedRequestSignature(r *http.Request) ([]byte, error) { const authHeaderSignatureElem = "Signature=" if auth := r.Header.Get(authorizationHeader); len(auth) != 0 { - ps := strings.Split(auth, ", ") + ps := strings.Split(auth, ",") for _, p := range ps { + p = strings.TrimSpace(p) if idx := strings.Index(p, authHeaderSignatureElem); idx >= 0 { sig := p[len(authHeaderSignatureElem):] if len(sig) == 0 { diff --git a/aws/signer/v4/middleware_test.go b/aws/signer/v4/middleware_test.go index 9b56ecefda5..6d7f85c1d54 100644 --- a/aws/signer/v4/middleware_test.go +++ b/aws/signer/v4/middleware_test.go @@ -3,6 +3,7 @@ package v4 import ( "bytes" "context" + "encoding/hex" "errors" "fmt" "io" @@ -372,6 +373,62 @@ func TestUseDynamicPayloadSigningMiddleware(t *testing.T) { } } +func TestGetSignedRequestSignature(t *testing.T) { + testCases := map[string]struct { + authHeader string + expectedSig string + expectedErrMsg string + }{ + "Valid signature": { + authHeader: "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024", + expectedSig: "fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024", + }, + "Whitespace after Signature": { + authHeader: "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024 ", + expectedSig: "fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024", + }, + "Whitespaces before Signature": { + authHeader: "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024 ", + expectedSig: "fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024", + }, + "Empty signature": { + authHeader: "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=", + expectedErrMsg: "invalid request signature authorization header", + }, + "Missing signature": { + authHeader: "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date", + expectedErrMsg: "request not signed", + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + r, err := http.NewRequest("GET", "/", nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + r.Header.Set("Authorization", tc.authHeader) + + sig, err := GetSignedRequestSignature(r) + + if tc.expectedErrMsg != "" { + if err == nil { + t.Errorf("Expected error with message '%s', but got no error", tc.expectedErrMsg) + } else if err.Error() != tc.expectedErrMsg { + t.Errorf("Expected error message '%s', but got '%s'", tc.expectedErrMsg, err.Error()) + } + } else { + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if hex.EncodeToString(sig) != tc.expectedSig { + t.Errorf("Expected signature '%s', but got '%s'", tc.expectedSig, hex.EncodeToString(sig)) + } + } + }) + } +} + type nonSeeker struct{} func (nonSeeker) Read(p []byte) (n int, err error) { diff --git a/service/.DS_Store b/service/.DS_Store new file mode 100644 index 00000000000..ccf5a4c129c Binary files /dev/null and b/service/.DS_Store differ