mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-31 01:10:41 +01:00
s3api: map truncated SigV4 headers to the error for the missing field
AWS answers an Authorization header missing Credential= with InvalidArgument and one missing or malformed Signature= with AuthorizationHeaderMalformed, instead of a generic MissingFields. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
eb744e71bd
commit
e068bd2167
3 files changed
+43
-5
No files matched your search
@@ -151,8 +151,20 @@ func parseSignV4(v4Auth string) (sv signValues, aec s3err.ErrorCode) {
|
||||
// Strip off the Algorithm prefix.
|
||||
v4Auth = strings.TrimPrefix(v4Auth, signV4Algorithm)
|
||||
authFields := strings.Split(strings.TrimSpace(v4Auth), ",")
|
||||
if len(authFields) != 3 {
|
||||
return sv, s3err.ErrMissingFields
|
||||
malformed := len(authFields) != 3
|
||||
var hasCredential, hasSignature bool
|
||||
for _, field := range authFields {
|
||||
field = strings.TrimSpace(field)
|
||||
malformed = malformed || field == ""
|
||||
hasCredential = hasCredential || strings.HasPrefix(field, "Credential=")
|
||||
hasSignature = hasSignature || strings.HasPrefix(field, "Signature=")
|
||||
}
|
||||
if malformed {
|
||||
// AWS distinguishes which required field is absent.
|
||||
if !hasCredential {
|
||||
return sv, s3err.ErrInvalidArgument
|
||||
}
|
||||
return sv, s3err.ErrAuthorizationHeaderMalformed
|
||||
}
|
||||
|
||||
// Initialize signature version '4' structured header.
|
||||
@@ -744,13 +756,13 @@ func parseCredentialHeader(credElement string) (ch credentialHeader, aec s3err.E
|
||||
func parseSignature(signElement string) (string, s3err.ErrorCode) {
|
||||
signFields := strings.Split(strings.TrimSpace(signElement), "=")
|
||||
if len(signFields) != 2 {
|
||||
return "", s3err.ErrMissingFields
|
||||
return "", s3err.ErrAuthorizationHeaderMalformed
|
||||
}
|
||||
if signFields[0] != "Signature" {
|
||||
return "", s3err.ErrMissingSignTag
|
||||
}
|
||||
if signFields[1] == "" {
|
||||
return "", s3err.ErrMissingFields
|
||||
return "", s3err.ErrAuthorizationHeaderMalformed
|
||||
}
|
||||
signature := signFields[1]
|
||||
return signature, s3err.ErrNone
|
||||
|
||||
@@ -360,3 +360,29 @@ func TestPresignedPutRejectsUnsignedMetadataHeaders(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseSignV4MissingFields exercises how a truncated Authorization header
|
||||
// maps to the AWS error code for the absent field.
|
||||
func TestParseSignV4MissingFields(t *testing.T) {
|
||||
valid := "AWS4-HMAC-SHA256 Credential=AKIA/20260101/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=0123456789abcdef"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
auth string
|
||||
want s3err.ErrorCode
|
||||
}{
|
||||
{"valid", valid, s3err.ErrNone},
|
||||
{"no signature field", "AWS4-HMAC-SHA256 Credential=AKIA/20260101/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date", s3err.ErrAuthorizationHeaderMalformed},
|
||||
{"empty signature field", "AWS4-HMAC-SHA256 Credential=AKIA/20260101/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, ", s3err.ErrAuthorizationHeaderMalformed},
|
||||
{"no credential field", "AWS4-HMAC-SHA256 SignedHeaders=host;x-amz-date, Signature=0123456789abcdef", s3err.ErrInvalidArgument},
|
||||
{"leading comma after dropping credential", "AWS4-HMAC-SHA256 , SignedHeaders=host;x-amz-date, Signature=0123456789abcdef", s3err.ErrInvalidArgument},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, got := parseSignV4(tt.auth)
|
||||
if got != tt.want {
|
||||
t.Fatalf("parseSignV4() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -486,7 +486,7 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrMissingSignTag: {
|
||||
Code: "AccessDenied",
|
||||
Code: "AuthorizationHeaderMalformed",
|
||||
Description: "Signature header missing Signature field.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user