mirror of
https://github.com/versity/versitygw.git
synced 2026-08-17 12:46:23 +00:00
Merge pull request #2114 from versity/sis/unsupported-sigv2
fix: reject SigV2 requests
This commit is contained in:
@@ -53,6 +53,10 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string,
|
||||
|
||||
// Check X-Amz-Date header
|
||||
date := ctx.Get("X-Amz-Date")
|
||||
if date == "" {
|
||||
// Fall back to `Date` header if `X-Amz-Date` is not set
|
||||
date = ctx.Get("Date")
|
||||
}
|
||||
if date == "" {
|
||||
return s3err.GetAPIError(s3err.ErrMissingDateHeader)
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ func VerifyPresignedV4Signature(root RootUserConfig, iam auth.IAMService, region
|
||||
if !utils.IsPresignedURLAuth(ctx) {
|
||||
return nil
|
||||
}
|
||||
if utils.IsPresignedURLAuthV2(ctx) {
|
||||
// SigV2 authorization is not supported by the gateway
|
||||
return s3err.GetAPIError(s3err.ErrUnsupportedAuthorizationMechanism)
|
||||
}
|
||||
|
||||
if ctx.Request().URI().QueryArgs().Has("X-Amz-Security-Token") {
|
||||
// OIDC Authorization with X-Amz-Security-Token is not supported
|
||||
|
||||
@@ -191,7 +191,10 @@ func ParseAuthorization(authorization string) (AuthData, error) {
|
||||
}
|
||||
|
||||
algo := authParts[0]
|
||||
|
||||
if algo == "AWS" {
|
||||
// SigV2 authorization is not supported by the gateway
|
||||
return a, s3err.GetAPIError(s3err.ErrUnsupportedAuthorizationMechanism)
|
||||
}
|
||||
if algo != "AWS4-HMAC-SHA256" {
|
||||
return a, s3err.GetAPIError(s3err.ErrUnsupportedAuthorizationType)
|
||||
}
|
||||
|
||||
@@ -254,11 +254,21 @@ func IsPresignedURLAuth(ctx *fiber.Ctx) bool {
|
||||
signedHeaders := ctx.Query("X-Amz-SignedHeaders")
|
||||
expires := ctx.Query("X-Amz-Expires")
|
||||
|
||||
return !isEmpty(algo, creds, signature, signedHeaders, expires)
|
||||
return !allEmpty(algo, creds, signature, signedHeaders, expires) || IsPresignedURLAuthV2(ctx)
|
||||
}
|
||||
|
||||
// isEmpty checks if all the given strings are empty
|
||||
func isEmpty(args ...string) bool {
|
||||
// IsPresignedURLAuthV2 determines if the request is
|
||||
// query-string signed with aws v2 signer
|
||||
func IsPresignedURLAuthV2(ctx *fiber.Ctx) bool {
|
||||
expires := ctx.Query("Expires")
|
||||
access := ctx.Query("AWSAccessKeyId")
|
||||
signature := ctx.Query("Signature")
|
||||
|
||||
return anyNonEmpty(expires, access, signature)
|
||||
}
|
||||
|
||||
// allEmpty reports whether every given string is empty.
|
||||
func allEmpty(args ...string) bool {
|
||||
for _, a := range args {
|
||||
if a != "" {
|
||||
return false
|
||||
@@ -267,3 +277,14 @@ func isEmpty(args ...string) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// anyNonEmpty reports whether at least one given string is non-empty.
|
||||
func anyNonEmpty(args ...string) bool {
|
||||
for _, a := range args {
|
||||
if a != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ const (
|
||||
ErrMetadataTooLarge
|
||||
ErrOnlyAws4HmacSha256
|
||||
ErrInvalidDateHeader
|
||||
ErrUnsupportedAuthorizationMechanism
|
||||
|
||||
// Non-AWS errors
|
||||
ErrExistingObjectIsDirectory
|
||||
@@ -868,6 +869,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "X-Amz-Date must be formated via ISO8601 Long format",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrUnsupportedAuthorizationMechanism: {
|
||||
Code: "InvalidRequest",
|
||||
Description: "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
// non aws errors
|
||||
ErrExistingObjectIsDirectory: {
|
||||
|
||||
@@ -38,6 +38,7 @@ func TestAuthentication(ts *TestState) {
|
||||
ts.Run(Authentication_invalid_sha256_payload_hash)
|
||||
ts.Run(Authentication_md5)
|
||||
ts.Run(Authentication_signature_error_incorrect_secret_key)
|
||||
ts.Run(Authentication_sigv2_not_supported)
|
||||
ts.Run(Authentication_with_expect_header)
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ func TestPresignedAuthentication(ts *TestState) {
|
||||
ts.Run(PresignedAuth_exceeding_expiration_query_param)
|
||||
ts.Run(PresignedAuth_expired_request)
|
||||
ts.Run(PresignedAuth_incorrect_secret_key)
|
||||
ts.Run(PresignedAuth_sigv2_not_supported)
|
||||
ts.Run(PresignedAuth_PutObject_success)
|
||||
ts.Run(PresignedAuth_Put_GetObject_with_data)
|
||||
if !ts.conf.azureTests {
|
||||
@@ -1293,6 +1295,7 @@ func GetIntTests() IntTests {
|
||||
"Authentication_invalid_sha256_payload_hash": Authentication_invalid_sha256_payload_hash,
|
||||
"Authentication_md5": Authentication_md5,
|
||||
"Authentication_signature_error_incorrect_secret_key": Authentication_signature_error_incorrect_secret_key,
|
||||
"Authentication_sigv2_not_supported": Authentication_sigv2_not_supported,
|
||||
"Authentication_with_expect_header": Authentication_with_expect_header,
|
||||
"PresignedAuth_security_token_not_supported": PresignedAuth_security_token_not_supported,
|
||||
"PresignedAuth_unsupported_algorithm": PresignedAuth_unsupported_algorithm,
|
||||
@@ -1314,6 +1317,7 @@ func GetIntTests() IntTests {
|
||||
"PresignedAuth_exceeding_expiration_query_param": PresignedAuth_exceeding_expiration_query_param,
|
||||
"PresignedAuth_expired_request": PresignedAuth_expired_request,
|
||||
"PresignedAuth_incorrect_secret_key": PresignedAuth_incorrect_secret_key,
|
||||
"PresignedAuth_sigv2_not_supported": PresignedAuth_sigv2_not_supported,
|
||||
"PresignedAuth_PutObject_success": PresignedAuth_PutObject_success,
|
||||
"PutObject_missing_object_lock_retention_config": PutObject_missing_object_lock_retention_config,
|
||||
"PutObject_name_too_long": PutObject_name_too_long,
|
||||
|
||||
@@ -665,6 +665,29 @@ func PresignedAuth_incorrect_secret_key(s *S3Conf) error {
|
||||
})
|
||||
}
|
||||
|
||||
func PresignedAuth_sigv2_not_supported(s *S3Conf) error {
|
||||
testName := "PresignedAuth_sigv2_not_supported"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
expires := time.Now().UTC().Add(time.Hour).Unix()
|
||||
uri := fmt.Sprintf("%s/%s/object?AWSAccessKeyId=%s&Expires=%d&Signature=my-signature", s.endpoint, bucket, s.awsID, expires)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, nil)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrUnsupportedAuthorizationMechanism))
|
||||
})
|
||||
}
|
||||
|
||||
func PresignedAuth_PutObject_success(s *S3Conf) error {
|
||||
testName := "PresignedAuth_PutObject_success"
|
||||
return presignedAuthHandler(s, testName, func(client *s3.PresignClient, bucket string) error {
|
||||
|
||||
@@ -564,6 +564,37 @@ func Authentication_signature_error_incorrect_secret_key(s *S3Conf) error {
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_sigv2_not_supported(s *S3Conf) error {
|
||||
testName := "Authentication_sigv2_not_supported"
|
||||
bucket := getBucketName()
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodPut,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
path: fmt.Sprintf("%s/object", bucket),
|
||||
}, func(req *http.Request) error {
|
||||
err := setup(s, bucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Del("Authorization")
|
||||
req.Header.Set("Authorization", "AWS seed_signature")
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrUnsupportedAuthorizationMechanism)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return teardown(s, bucket)
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_with_expect_header(s *S3Conf) error {
|
||||
testName := "Authentication_with_expect_header"
|
||||
bucket, object := getBucketName(), "object"
|
||||
|
||||
Reference in New Issue
Block a user