mirror of
https://github.com/versity/versitygw.git
synced 2026-04-24 14:40:30 +00:00
fix: fixes sigv4 and presigned url auth errors.
Fixes #1540 Fixes #1538 Fixes #1513 Fixes #1425 Fixes SigV4 authentication and presigned URL error handling. Adds two sets of errors in the `s3err` package for these authentication mechanisms. * Adds a check to return a custom "not supported" error when `X-Amz-Security-Token` is present in presigned URLs. * Adds a check to return a custom "not supported" error when the `AWS4-ECDSA-P256-SHA256` algorithm is used in presigned URLs.
This commit is contained in:
@@ -17,9 +17,7 @@ package middlewares
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -52,9 +50,27 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check X-Amz-Date header
|
||||
date := ctx.Get("X-Amz-Date")
|
||||
if date == "" {
|
||||
return s3err.GetAPIError(s3err.ErrMissingDateHeader)
|
||||
}
|
||||
|
||||
// Parse the date and check the date validity
|
||||
tdate, err := time.Parse(iso8601Format, date)
|
||||
if err != nil {
|
||||
return s3err.GetAPIError(s3err.ErrMissingDateHeader)
|
||||
}
|
||||
|
||||
// Validate the dates difference
|
||||
err = utils.ValidateDate(tdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authorization := ctx.Get("Authorization")
|
||||
if authorization == "" {
|
||||
return s3err.GetAPIError(s3err.ErrAuthHeaderEmpty)
|
||||
return s3err.GetAPIError(s3err.ErrInvalidAuthHeader)
|
||||
}
|
||||
|
||||
authData, err := utils.ParseAuthorization(authorization)
|
||||
@@ -63,11 +79,7 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string)
|
||||
}
|
||||
|
||||
if authData.Region != region {
|
||||
return s3err.APIError{
|
||||
Code: "SignatureDoesNotMatch",
|
||||
Description: fmt.Sprintf("Credential should be scoped to a valid Region, not %v", authData.Region),
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
}
|
||||
return s3err.MalformedAuth.IncorrectRegion(region, authData.Region)
|
||||
}
|
||||
|
||||
utils.ContextKeyIsRoot.Set(ctx, authData.Access == root.Access)
|
||||
@@ -80,29 +92,11 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string)
|
||||
return err
|
||||
}
|
||||
|
||||
utils.ContextKeyAccount.Set(ctx, account)
|
||||
|
||||
// Check X-Amz-Date header
|
||||
date := ctx.Get("X-Amz-Date")
|
||||
if date == "" {
|
||||
return s3err.GetAPIError(s3err.ErrMissingDateHeader)
|
||||
}
|
||||
|
||||
// Parse the date and check the date validity
|
||||
tdate, err := time.Parse(iso8601Format, date)
|
||||
if err != nil {
|
||||
return s3err.GetAPIError(s3err.ErrMalformedDate)
|
||||
}
|
||||
|
||||
if date[:8] != authData.Date {
|
||||
return s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)
|
||||
return s3err.MalformedAuth.DateMismatch()
|
||||
}
|
||||
|
||||
// Validate the dates difference
|
||||
err = utils.ValidateDate(tdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
utils.ContextKeyAccount.Set(ctx, account)
|
||||
|
||||
var contentLength int64
|
||||
contentLengthStr := ctx.Get("Content-Length")
|
||||
|
||||
@@ -32,10 +32,15 @@ func VerifyPresignedV4Signature(root RootUserConfig, iam auth.IAMService, region
|
||||
if utils.ContextKeyPublicBucket.IsSet(ctx) {
|
||||
return nil
|
||||
}
|
||||
if ctx.Query("X-Amz-Signature") == "" {
|
||||
if !utils.IsPresignedURLAuth(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ctx.Request().URI().QueryArgs().Has("X-Amz-Security-Token") {
|
||||
// OIDC Authorization with X-Amz-Security-Token is not supported
|
||||
return s3err.QueryAuthErrors.SecurityTokenNotSupported()
|
||||
}
|
||||
|
||||
// Set in the context the "authenticated" key, in case the authentication succeeds,
|
||||
// otherwise the middleware will return the caucht error
|
||||
utils.ContextKeyAuthenticated.Set(ctx, true)
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
func AuthorizePublicBucketAccess(be backend.Backend, s3action string, policyPermission auth.Action, permission auth.Permission) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
// skip for authenticated requests
|
||||
if ctx.Query("X-Amz-Algorithm") != "" || ctx.Get("Authorization") != "" {
|
||||
if utils.IsPresignedURLAuth(ctx) || ctx.Get("Authorization") != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ func (ar *AuthReader) validateSignature() error {
|
||||
// Parse the date and check the date validity
|
||||
tdate, err := time.Parse(iso8601Format, date)
|
||||
if err != nil {
|
||||
return s3err.GetAPIError(s3err.ErrMalformedDate)
|
||||
return s3err.GetAPIError(s3err.ErrMissingDateHeader)
|
||||
}
|
||||
|
||||
return CheckValidSignature(ar.ctx, ar.auth, ar.secret, hashPayload, tdate, int64(ar.size))
|
||||
@@ -184,54 +184,61 @@ func ParseAuthorization(authorization string) (AuthData, error) {
|
||||
}
|
||||
|
||||
if len(authParts) < 2 {
|
||||
return a, s3err.GetAPIError(s3err.ErrMissingFields)
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidAuthHeader)
|
||||
}
|
||||
|
||||
algo := authParts[0]
|
||||
|
||||
if algo != "AWS4-HMAC-SHA256" {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureVersionNotSupported)
|
||||
return a, s3err.GetAPIError(s3err.ErrUnsupportedAuthorizationType)
|
||||
}
|
||||
|
||||
kvData := authParts[1]
|
||||
kvPairs := strings.Split(kvData, ",")
|
||||
// we are expecting at least Credential, SignedHeaders, and Signature
|
||||
// key value pairs here
|
||||
if len(kvPairs) < 3 {
|
||||
return a, s3err.GetAPIError(s3err.ErrMissingFields)
|
||||
if len(kvPairs) != 3 {
|
||||
return a, s3err.MalformedAuth.MissingComponents()
|
||||
}
|
||||
|
||||
var access, region, signedHeaders, signature, date string
|
||||
|
||||
for _, kv := range kvPairs {
|
||||
for i, kv := range kvPairs {
|
||||
keyValue := strings.Split(kv, "=")
|
||||
if len(keyValue) != 2 {
|
||||
switch {
|
||||
case strings.HasPrefix(kv, "Credential"):
|
||||
return a, s3err.GetAPIError(s3err.ErrCredMalformed)
|
||||
case strings.HasPrefix(kv, "SignedHeaders"):
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidQueryParams)
|
||||
}
|
||||
return a, s3err.GetAPIError(s3err.ErrMissingFields)
|
||||
return a, s3err.MalformedAuth.MalformedComponent(kv)
|
||||
}
|
||||
key, value := keyValue[0], keyValue[1]
|
||||
switch i {
|
||||
case 0:
|
||||
if key != "Credential" {
|
||||
return a, s3err.MalformedAuth.MissingCredential()
|
||||
}
|
||||
case 1:
|
||||
if key != "SignedHeaders" {
|
||||
return a, s3err.MalformedAuth.MissingSignedHeaders()
|
||||
}
|
||||
case 2:
|
||||
if key != "Signature" {
|
||||
return a, s3err.MalformedAuth.MissingSignature()
|
||||
}
|
||||
}
|
||||
key := strings.TrimSpace(keyValue[0])
|
||||
value := strings.TrimSpace(keyValue[1])
|
||||
|
||||
switch key {
|
||||
case "Credential":
|
||||
creds := strings.Split(value, "/")
|
||||
if len(creds) != 5 {
|
||||
return a, s3err.GetAPIError(s3err.ErrCredMalformed)
|
||||
return a, s3err.MalformedAuth.MalformedCredential()
|
||||
}
|
||||
if creds[3] != "s3" {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureIncorrService)
|
||||
return a, s3err.MalformedAuth.IncorrectService(creds[3])
|
||||
}
|
||||
if creds[4] != "aws4_request" {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureTerminationStr)
|
||||
return a, s3err.MalformedAuth.InvalidTerminal(creds[4])
|
||||
}
|
||||
_, err := time.Parse(yyyymmdd, creds[1])
|
||||
if err != nil {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)
|
||||
return a, s3err.MalformedAuth.InvalidDateFormat(creds[1])
|
||||
}
|
||||
access = creds[0]
|
||||
date = creds[1]
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -35,6 +34,9 @@ import (
|
||||
|
||||
const (
|
||||
unsignedPayload string = "UNSIGNED-PAYLOAD"
|
||||
|
||||
algoHMAC string = "AWS4-HMAC-SHA256"
|
||||
algoECDSA string = "AWS4-ECDSA-P256-SHA256"
|
||||
)
|
||||
|
||||
// PresignedAuthReader is an io.Reader that validates presigned request authorization
|
||||
@@ -136,65 +138,70 @@ func ParsePresignedURIParts(ctx *fiber.Ctx) (AuthData, error) {
|
||||
|
||||
// Get and verify algorithm query parameter
|
||||
algo := ctx.Query("X-Amz-Algorithm")
|
||||
if algo == "" {
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidQueryParams)
|
||||
}
|
||||
if algo != "AWS4-HMAC-SHA256" {
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidQuerySignatureAlgo)
|
||||
err := validateAlgorithm(algo)
|
||||
if err != nil {
|
||||
return a, err
|
||||
}
|
||||
|
||||
// Parse and validate credentials query parameter
|
||||
credsQuery := ctx.Query("X-Amz-Credential")
|
||||
if credsQuery == "" {
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidQueryParams)
|
||||
return a, s3err.QueryAuthErrors.MissingRequiredParams()
|
||||
}
|
||||
|
||||
creds := strings.Split(credsQuery, "/")
|
||||
if len(creds) != 5 {
|
||||
return a, s3err.GetAPIError(s3err.ErrCredMalformed)
|
||||
return a, s3err.QueryAuthErrors.MalformedCredential()
|
||||
}
|
||||
|
||||
// validate the service
|
||||
if creds[3] != "s3" {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureIncorrService)
|
||||
return a, s3err.QueryAuthErrors.IncorrectService(creds[3])
|
||||
}
|
||||
|
||||
// validate the terminal
|
||||
if creds[4] != "aws4_request" {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureTerminationStr)
|
||||
return a, s3err.QueryAuthErrors.IncorrectTerminal(creds[4])
|
||||
}
|
||||
_, err := time.Parse(yyyymmdd, creds[1])
|
||||
|
||||
// validate the date
|
||||
_, err = time.Parse(yyyymmdd, creds[1])
|
||||
if err != nil {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)
|
||||
return a, s3err.QueryAuthErrors.InvalidDateFormat(creds[1])
|
||||
}
|
||||
|
||||
region, ok := ContextKeyRegion.Get(ctx).(string)
|
||||
if !ok {
|
||||
region = ""
|
||||
}
|
||||
// validate the region
|
||||
if creds[2] != region {
|
||||
return a, s3err.QueryAuthErrors.IncorrectRegion(region, creds[2])
|
||||
}
|
||||
|
||||
// Parse and validate Date query param
|
||||
date := ctx.Query("X-Amz-Date")
|
||||
if date == "" {
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidQueryParams)
|
||||
return a, s3err.QueryAuthErrors.MissingRequiredParams()
|
||||
}
|
||||
|
||||
tdate, err := time.Parse(iso8601Format, date)
|
||||
if err != nil {
|
||||
return a, s3err.GetAPIError(s3err.ErrMalformedDate)
|
||||
return a, s3err.QueryAuthErrors.InvalidXAmzDateFormat()
|
||||
}
|
||||
|
||||
if date[:8] != creds[1] {
|
||||
return a, s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)
|
||||
}
|
||||
|
||||
if ContextKeyRegion.Get(ctx) != creds[2] {
|
||||
return a, s3err.APIError{
|
||||
Code: "SignatureDoesNotMatch",
|
||||
Description: fmt.Sprintf("Credential should be scoped to a valid Region, not %v", creds[2]),
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
}
|
||||
return a, s3err.QueryAuthErrors.DateMismatch(creds[1], date[:8])
|
||||
}
|
||||
|
||||
signature := ctx.Query("X-Amz-Signature")
|
||||
if signature == "" {
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidQueryParams)
|
||||
return a, s3err.QueryAuthErrors.MissingRequiredParams()
|
||||
}
|
||||
|
||||
signedHdrs := ctx.Query("X-Amz-SignedHeaders")
|
||||
if signedHdrs == "" {
|
||||
return a, s3err.GetAPIError(s3err.ErrInvalidQueryParams)
|
||||
return a, s3err.QueryAuthErrors.MissingRequiredParams()
|
||||
}
|
||||
|
||||
// Validate X-Amz-Expires query param and check if request is expired
|
||||
@@ -215,20 +222,20 @@ func ParsePresignedURIParts(ctx *fiber.Ctx) (AuthData, error) {
|
||||
|
||||
func validateExpiration(str string, date time.Time) error {
|
||||
if str == "" {
|
||||
return s3err.GetAPIError(s3err.ErrInvalidQueryParams)
|
||||
return s3err.QueryAuthErrors.MissingRequiredParams()
|
||||
}
|
||||
|
||||
exp, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
return s3err.GetAPIError(s3err.ErrMalformedExpires)
|
||||
return s3err.QueryAuthErrors.ExpiresNumber()
|
||||
}
|
||||
|
||||
if exp < 0 {
|
||||
return s3err.GetAPIError(s3err.ErrNegativeExpires)
|
||||
return s3err.QueryAuthErrors.ExpiresNegative()
|
||||
}
|
||||
|
||||
if exp > 604800 {
|
||||
return s3err.GetAPIError(s3err.ErrMaximumExpires)
|
||||
return s3err.QueryAuthErrors.ExpiresTooLarge()
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
@@ -240,3 +247,43 @@ func validateExpiration(str string, date time.Time) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateAlgorithm validates the algorithm
|
||||
// for AWS4-ECDSA-P256-SHA256 it returns a custom non AWS error
|
||||
// currently only AWS4-HMAC-SHA256 algorithm is supported
|
||||
func validateAlgorithm(algo string) error {
|
||||
switch algo {
|
||||
case "":
|
||||
return s3err.QueryAuthErrors.MissingRequiredParams()
|
||||
case algoHMAC:
|
||||
return nil
|
||||
case algoECDSA:
|
||||
return s3err.QueryAuthErrors.OnlyHMACSupported()
|
||||
default:
|
||||
// all other algorithms are considerd as invalid
|
||||
return s3err.QueryAuthErrors.UnsupportedAlgorithm()
|
||||
}
|
||||
}
|
||||
|
||||
// IsPresignedURLAuth determines if the request is presigned:
|
||||
// which is authorization with query params
|
||||
func IsPresignedURLAuth(ctx *fiber.Ctx) bool {
|
||||
algo := ctx.Query("X-Amz-Algorithm")
|
||||
creds := ctx.Query("X-Amz-Credential")
|
||||
signature := ctx.Query("X-Amz-Signature")
|
||||
signedHeaders := ctx.Query("X-Amz-SignedHeaders")
|
||||
expires := ctx.Query("X-Amz-Expires")
|
||||
|
||||
return !isEmpty(algo, creds, signature, signedHeaders, expires)
|
||||
}
|
||||
|
||||
// isEmpty checks if all the given strings are empty
|
||||
func isEmpty(args ...string) bool {
|
||||
for _, a := range args {
|
||||
if a != "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,7 @@ func Test_validateExpiration(t *testing.T) {
|
||||
str: "",
|
||||
date: time.Now(),
|
||||
},
|
||||
err: s3err.GetAPIError(s3err.ErrInvalidQueryParams),
|
||||
err: s3err.QueryAuthErrors.MissingRequiredParams(),
|
||||
},
|
||||
{
|
||||
name: "invalid-expiration",
|
||||
@@ -45,7 +46,7 @@ func Test_validateExpiration(t *testing.T) {
|
||||
str: "invalid_expiration",
|
||||
date: time.Now(),
|
||||
},
|
||||
err: s3err.GetAPIError(s3err.ErrMalformedExpires),
|
||||
err: s3err.QueryAuthErrors.ExpiresNumber(),
|
||||
},
|
||||
{
|
||||
name: "negative-expiration",
|
||||
@@ -53,7 +54,7 @@ func Test_validateExpiration(t *testing.T) {
|
||||
str: "-320",
|
||||
date: time.Now(),
|
||||
},
|
||||
err: s3err.GetAPIError(s3err.ErrNegativeExpires),
|
||||
err: s3err.QueryAuthErrors.ExpiresNegative(),
|
||||
},
|
||||
{
|
||||
name: "exceeding-expiration",
|
||||
@@ -61,7 +62,7 @@ func Test_validateExpiration(t *testing.T) {
|
||||
str: "6048000",
|
||||
date: time.Now(),
|
||||
},
|
||||
err: s3err.GetAPIError(s3err.ErrMaximumExpires),
|
||||
err: s3err.QueryAuthErrors.ExpiresTooLarge(),
|
||||
},
|
||||
{
|
||||
name: "expired value",
|
||||
@@ -98,3 +99,22 @@ func Test_validateExpiration(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_validateAlgorithm(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
algo string
|
||||
err error
|
||||
}{
|
||||
{"empty", "", s3err.QueryAuthErrors.MissingRequiredParams()},
|
||||
{"AWS4-HMAC-SHA256", "AWS4-HMAC-SHA256", nil},
|
||||
{"AWS4-ECDSA-P256-SHA256", "AWS4-ECDSA-P256-SHA256", s3err.QueryAuthErrors.OnlyHMACSupported()},
|
||||
{"invalid", "invalid algo", s3err.QueryAuthErrors.UnsupportedAlgorithm()},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := validateAlgorithm(tt.algo)
|
||||
assert.EqualValues(t, tt.err, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
95
s3err/presigned-urls.go
Normal file
95
s3err/presigned-urls.go
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright 2023 Versity Software
|
||||
// This file is licensed under the Apache License, Version 2.0
|
||||
// (the "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package s3err
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Factory for building AuthorizationQueryParametersError errors.
|
||||
func authQueryParamError(format string, args ...any) APIError {
|
||||
return APIError{
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: fmt.Sprintf(format, args...),
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
}
|
||||
}
|
||||
|
||||
var QueryAuthErrors = struct {
|
||||
UnsupportedAlgorithm func() APIError
|
||||
MalformedCredential func() APIError
|
||||
IncorrectService func(string) APIError
|
||||
IncorrectRegion func(expected, actual string) APIError
|
||||
IncorrectTerminal func(string) APIError
|
||||
InvalidDateFormat func(string) APIError
|
||||
DateMismatch func(expected, actual string) APIError
|
||||
ExpiresTooLarge func() APIError
|
||||
ExpiresNegative func() APIError
|
||||
ExpiresNumber func() APIError
|
||||
MissingRequiredParams func() APIError
|
||||
InvalidXAmzDateFormat func() APIError
|
||||
RequestNotYetValid func() APIError
|
||||
RequestExpired func() APIError
|
||||
InvalidAccessKeyId func() APIError
|
||||
// a custom non-AWS error
|
||||
OnlyHMACSupported func() APIError
|
||||
SecurityTokenNotSupported func() APIError
|
||||
}{
|
||||
|
||||
UnsupportedAlgorithm: func() APIError {
|
||||
return authQueryParamError(`X-Amz-Algorithm only supports "AWS4-HMAC-SHA256 and AWS4-ECDSA-P256-SHA256"`)
|
||||
},
|
||||
MalformedCredential: func() APIError {
|
||||
return authQueryParamError(`Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting "<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request".`)
|
||||
},
|
||||
IncorrectService: func(s string) APIError {
|
||||
return authQueryParamError(`Error parsing the X-Amz-Credential parameter; incorrect service %q. This endpoint belongs to "s3".`, s)
|
||||
},
|
||||
IncorrectRegion: func(expected, actual string) APIError {
|
||||
return authQueryParamError(`Error parsing the X-Amz-Credential parameter; the region %q is wrong; expecting %q`, actual, expected)
|
||||
},
|
||||
IncorrectTerminal: func(s string) APIError {
|
||||
return authQueryParamError(`Error parsing the X-Amz-Credential parameter; incorrect terminal %q. This endpoint uses "aws4_request".`, s)
|
||||
},
|
||||
InvalidDateFormat: func(s string) APIError {
|
||||
return authQueryParamError(`Error parsing the X-Amz-Credential parameter; incorrect date format %q. This date in the credential must be in the format "yyyyMMdd".`, s)
|
||||
},
|
||||
DateMismatch: func(expected, actual string) APIError {
|
||||
return authQueryParamError(`Invalid credential date %q. This date is not the same as X-Amz-Date: %q.`, expected, actual)
|
||||
},
|
||||
ExpiresTooLarge: func() APIError {
|
||||
return authQueryParamError("X-Amz-Expires must be less than a week (in seconds); that is, the given X-Amz-Expires must be less than 604800 seconds")
|
||||
},
|
||||
ExpiresNegative: func() APIError {
|
||||
return authQueryParamError("X-Amz-Expires must be non-negative")
|
||||
},
|
||||
ExpiresNumber: func() APIError {
|
||||
return authQueryParamError("X-Amz-Expires should be a number")
|
||||
},
|
||||
MissingRequiredParams: func() APIError {
|
||||
return authQueryParamError("Query-string authentication version 4 requires the X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, X-Amz-Date, X-Amz-SignedHeaders, and X-Amz-Expires parameters.")
|
||||
},
|
||||
InvalidXAmzDateFormat: func() APIError {
|
||||
return authQueryParamError(`X-Amz-Date must be in the ISO8601 Long Format "yyyyMMdd'T'HHmmss'Z'"`)
|
||||
},
|
||||
// a custom non-AWS error
|
||||
OnlyHMACSupported: func() APIError {
|
||||
return authQueryParamError("X-Amz-Algorithm only supports \"AWS4-HMAC-SHA256\"")
|
||||
},
|
||||
SecurityTokenNotSupported: func() APIError {
|
||||
return authQueryParamError("Authorization with X-Amz-Security-Token is not supported")
|
||||
},
|
||||
}
|
||||
@@ -98,8 +98,8 @@ const (
|
||||
ErrBucketTaggingLimited
|
||||
ErrObjectTaggingLimited
|
||||
ErrInvalidURLEncodedTagging
|
||||
ErrAuthHeaderEmpty
|
||||
ErrSignatureVersionNotSupported
|
||||
ErrInvalidAuthHeader
|
||||
ErrUnsupportedAuthorizationType
|
||||
ErrMalformedPOSTRequest
|
||||
ErrPOSTFileRequired
|
||||
ErrPostPolicyConditionInvalidFormat
|
||||
@@ -107,24 +107,13 @@ const (
|
||||
ErrEntityTooLarge
|
||||
ErrMissingFields
|
||||
ErrMissingCredTag
|
||||
ErrCredMalformed
|
||||
ErrMalformedXML
|
||||
ErrMalformedDate
|
||||
ErrMalformedPresignedDate
|
||||
ErrMalformedCredentialDate
|
||||
ErrMissingSignHeadersTag
|
||||
ErrMissingSignTag
|
||||
ErrUnsignedHeaders
|
||||
ErrInvalidQueryParams
|
||||
ErrInvalidQuerySignatureAlgo
|
||||
ErrExpiredPresignRequest
|
||||
ErrMalformedExpires
|
||||
ErrNegativeExpires
|
||||
ErrMaximumExpires
|
||||
ErrSignatureDoesNotMatch
|
||||
ErrSignatureDateDoesNotMatch
|
||||
ErrSignatureTerminationStr
|
||||
ErrSignatureIncorrService
|
||||
ErrContentSHA256Mismatch
|
||||
ErrInvalidSHA256Paylod
|
||||
ErrMissingContentLength
|
||||
@@ -402,14 +391,14 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "The XML you provided was not well-formed or did not validate against our published schema.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrAuthHeaderEmpty: {
|
||||
ErrInvalidAuthHeader: {
|
||||
Code: "InvalidArgument",
|
||||
Description: "Authorization header is invalid -- one and only one ' ' (space) required.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrSignatureVersionNotSupported: {
|
||||
Code: "InvalidRequest",
|
||||
Description: "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.",
|
||||
ErrUnsupportedAuthorizationType: {
|
||||
Code: "InvalidArgument",
|
||||
Description: "Unsupported Authorization Type",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrMalformedPOSTRequest: {
|
||||
@@ -447,21 +436,6 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "Missing Credential field for this request.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrCredMalformed: {
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: "Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting \"<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request\".",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrMalformedDate: {
|
||||
Code: "MalformedDate",
|
||||
Description: "Invalid date format header, expected to be in ISO8601, RFC1123 or RFC1123Z time format.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrMalformedPresignedDate: {
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: "X-Amz-Date must be in the ISO8601 Long Format \"yyyyMMdd'T'HHmmss'Z'\".",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrMissingSignHeadersTag: {
|
||||
Code: "InvalidArgument",
|
||||
Description: "Signature header missing SignedHeaders field.",
|
||||
@@ -477,36 +451,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "There were headers present in the request which were not signed.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrInvalidQueryParams: {
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: "Query-string authentication version 4 requires the X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, X-Amz-Date, X-Amz-SignedHeaders, and X-Amz-Expires parameters.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrInvalidQuerySignatureAlgo: {
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: "X-Amz-Algorithm only supports \"AWS4-HMAC-SHA256\".",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrExpiredPresignRequest: {
|
||||
Code: "AccessDenied",
|
||||
Description: "Request has expired.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
ErrMalformedExpires: {
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: "X-Amz-Expires should be a number.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrNegativeExpires: {
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: "X-Amz-Expires must be non-negative.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrMaximumExpires: {
|
||||
Code: "AuthorizationQueryParametersError",
|
||||
Description: "X-Amz-Expires must be less than a week (in seconds); that is, the given X-Amz-Expires must be less than 604800 seconds.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrInvalidAccessKeyID: {
|
||||
Code: "InvalidAccessKeyId",
|
||||
Description: "The AWS Access Key Id you provided does not exist in our records.",
|
||||
@@ -522,21 +471,6 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "The request signature we calculated does not match the signature you provided. Check your key and signing method.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
ErrSignatureDateDoesNotMatch: {
|
||||
Code: "SignatureDoesNotMatch",
|
||||
Description: "Date in Credential scope does not match YYYYMMDD from ISO-8601 version of date from HTTP.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
ErrSignatureTerminationStr: {
|
||||
Code: "SignatureDoesNotMatch",
|
||||
Description: "Credential should be scoped with a valid terminator: 'aws4_request'.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
ErrSignatureIncorrService: {
|
||||
Code: "SignatureDoesNotMatch",
|
||||
Description: "Credential should be scoped to correct service: s3.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
ErrContentSHA256Mismatch: {
|
||||
Code: "XAmzContentSHA256Mismatch",
|
||||
Description: "The provided 'x-amz-content-sha256' header does not match what was computed.",
|
||||
@@ -659,7 +593,7 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
},
|
||||
ErrRequestTimeTooSkewed: {
|
||||
Code: "RequestTimeTooSkewed",
|
||||
Description: "The difference between the request time and the server's time is too large.",
|
||||
Description: "The difference between the request time and the current time is too large.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
ErrInvalidBucketAclWithObjectOwnership: {
|
||||
|
||||
77
s3err/sigv4.go
Normal file
77
s3err/sigv4.go
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2023 Versity Software
|
||||
// This file is licensed under the Apache License, Version 2.0
|
||||
// (the "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package s3err
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Factory for building AuthorizationHeaderMalformed errors.
|
||||
func malformedAuthError(format string, args ...any) APIError {
|
||||
return APIError{
|
||||
Code: "AuthorizationHeaderMalformed",
|
||||
Description: fmt.Sprintf("The authorization header is malformed; %s", fmt.Sprintf(format, args...)),
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
}
|
||||
}
|
||||
|
||||
var MalformedAuth = struct {
|
||||
InvalidDateFormat func(string) APIError
|
||||
MalformedCredential func() APIError
|
||||
MissingCredential func() APIError
|
||||
MissingSignature func() APIError
|
||||
MissingSignedHeaders func() APIError
|
||||
InvalidTerminal func(string) APIError
|
||||
IncorrectRegion func(expected, actual string) APIError
|
||||
IncorrectService func(string) APIError
|
||||
MalformedComponent func(string) APIError
|
||||
MissingComponents func() APIError
|
||||
DateMismatch func() APIError
|
||||
}{
|
||||
InvalidDateFormat: func(s string) APIError {
|
||||
return malformedAuthError("incorrect date format %q. This date in the credential must be in the format \"yyyyMMdd\".", s)
|
||||
},
|
||||
MalformedCredential: func() APIError {
|
||||
return malformedAuthError("the Credential is mal-formed; expecting \"<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request\".")
|
||||
},
|
||||
MissingCredential: func() APIError {
|
||||
return malformedAuthError("missing Credential.")
|
||||
},
|
||||
MissingSignature: func() APIError {
|
||||
return malformedAuthError("missing Signature.")
|
||||
},
|
||||
MissingSignedHeaders: func() APIError {
|
||||
return malformedAuthError("missing SignedHeaders.")
|
||||
},
|
||||
InvalidTerminal: func(s string) APIError {
|
||||
return malformedAuthError("incorrect terminal %q. This endpoint uses \"aws4_request\".", s)
|
||||
},
|
||||
IncorrectRegion: func(expected, actual string) APIError {
|
||||
return malformedAuthError("the region %q is wrong; expecting %q", actual, expected)
|
||||
},
|
||||
IncorrectService: func(s string) APIError {
|
||||
return malformedAuthError("incorrect service %q. This endpoint belongs to \"s3\".", s)
|
||||
},
|
||||
MalformedComponent: func(s string) APIError {
|
||||
return malformedAuthError("the authorization component %q is malformed.", s)
|
||||
},
|
||||
MissingComponents: func() APIError {
|
||||
return malformedAuthError("the authorization header requires three components: Credential, SignedHeaders, and Signature.")
|
||||
},
|
||||
DateMismatch: func() APIError {
|
||||
return malformedAuthError("The authorization header is malformed; Invalid credential date. Date is not the same as X-Amz-Date.")
|
||||
},
|
||||
}
|
||||
@@ -17,16 +17,20 @@ package integration
|
||||
func TestAuthentication(s *S3Conf) {
|
||||
Authentication_invalid_auth_header(s)
|
||||
Authentication_unsupported_signature_version(s)
|
||||
Authentication_malformed_credentials(s)
|
||||
Authentication_malformed_credentials_invalid_parts(s)
|
||||
Authentication_credentials_terminated_string(s)
|
||||
Authentication_missing_components(s)
|
||||
Authentication_malformed_component(s)
|
||||
Authentication_missing_credentials(s)
|
||||
Authentication_missing_signedheaders(s)
|
||||
Authentication_missing_signature(s)
|
||||
Authentication_malformed_credential(s)
|
||||
Authentication_credentials_invalid_terminal(s)
|
||||
Authentication_credentials_incorrect_service(s)
|
||||
Authentication_credentials_incorrect_region(s)
|
||||
Authentication_credentials_invalid_date(s)
|
||||
Authentication_credentials_future_date(s)
|
||||
Authentication_credentials_past_date(s)
|
||||
Authentication_credentials_non_existing_access_key(s)
|
||||
Authentication_invalid_signed_headers(s)
|
||||
//TODO: handle the case with signed headers
|
||||
Authentication_missing_date_header(s)
|
||||
Authentication_invalid_date_header(s)
|
||||
Authentication_date_mismatch(s)
|
||||
@@ -37,10 +41,13 @@ func TestAuthentication(s *S3Conf) {
|
||||
}
|
||||
|
||||
func TestPresignedAuthentication(s *S3Conf) {
|
||||
PresignedAuth_security_token_not_supported(s)
|
||||
PresignedAuth_unsupported_algorithm(s)
|
||||
PresignedAuth_ECDSA_not_supported(s)
|
||||
PresignedAuth_missing_signature_query_param(s)
|
||||
PresignedAuth_missing_credentials_query_param(s)
|
||||
PresignedAuth_malformed_creds_invalid_parts(s)
|
||||
PresignedAuth_malformed_creds_invalid_parts(s)
|
||||
PresignedAuth_creds_invalid_terminal(s)
|
||||
PresignedAuth_creds_incorrect_service(s)
|
||||
PresignedAuth_creds_incorrect_region(s)
|
||||
PresignedAuth_creds_invalid_date(s)
|
||||
@@ -1020,16 +1027,19 @@ func GetIntTests() IntTests {
|
||||
return IntTests{
|
||||
"Authentication_invalid_auth_header": Authentication_invalid_auth_header,
|
||||
"Authentication_unsupported_signature_version": Authentication_unsupported_signature_version,
|
||||
"Authentication_malformed_credentials": Authentication_malformed_credentials,
|
||||
"Authentication_malformed_credentials_invalid_parts": Authentication_malformed_credentials_invalid_parts,
|
||||
"Authentication_credentials_terminated_string": Authentication_credentials_terminated_string,
|
||||
"Authentication_missing_components": Authentication_missing_components,
|
||||
"Authentication_malformed_component": Authentication_malformed_component,
|
||||
"Authentication_missing_credentials": Authentication_missing_credentials,
|
||||
"Authentication_missing_signedheaders": Authentication_missing_signedheaders,
|
||||
"Authentication_missing_signature": Authentication_missing_signature,
|
||||
"Authentication_malformed_credential": Authentication_malformed_credential,
|
||||
"Authentication_credentials_invalid_terminal": Authentication_credentials_invalid_terminal,
|
||||
"Authentication_credentials_incorrect_service": Authentication_credentials_incorrect_service,
|
||||
"Authentication_credentials_incorrect_region": Authentication_credentials_incorrect_region,
|
||||
"Authentication_credentials_invalid_date": Authentication_credentials_invalid_date,
|
||||
"Authentication_credentials_future_date": Authentication_credentials_future_date,
|
||||
"Authentication_credentials_past_date": Authentication_credentials_past_date,
|
||||
"Authentication_credentials_non_existing_access_key": Authentication_credentials_non_existing_access_key,
|
||||
"Authentication_invalid_signed_headers": Authentication_invalid_signed_headers,
|
||||
"Authentication_missing_date_header": Authentication_missing_date_header,
|
||||
"Authentication_invalid_date_header": Authentication_invalid_date_header,
|
||||
"Authentication_date_mismatch": Authentication_date_mismatch,
|
||||
@@ -1037,10 +1047,13 @@ func GetIntTests() IntTests {
|
||||
"Authentication_invalid_sha256_payload_hash": Authentication_invalid_sha256_payload_hash,
|
||||
"Authentication_incorrect_md5": Authentication_incorrect_md5,
|
||||
"Authentication_signature_error_incorrect_secret_key": Authentication_signature_error_incorrect_secret_key,
|
||||
"PresignedAuth_security_token_not_supported": PresignedAuth_security_token_not_supported,
|
||||
"PresignedAuth_unsupported_algorithm": PresignedAuth_unsupported_algorithm,
|
||||
"PresignedAuth_ECDSA_not_supported": PresignedAuth_ECDSA_not_supported,
|
||||
"PresignedAuth_missing_signature_query_param": PresignedAuth_missing_signature_query_param,
|
||||
"PresignedAuth_missing_credentials_query_param": PresignedAuth_missing_credentials_query_param,
|
||||
"PresignedAuth_malformed_creds_invalid_parts": PresignedAuth_malformed_creds_invalid_parts,
|
||||
"PresignedAuth_creds_invalid_terminator": PresignedAuth_creds_invalid_terminator,
|
||||
"PresignedAuth_creds_invalid_terminal": PresignedAuth_creds_invalid_terminal,
|
||||
"PresignedAuth_creds_incorrect_service": PresignedAuth_creds_incorrect_service,
|
||||
"PresignedAuth_creds_incorrect_region": PresignedAuth_creds_incorrect_region,
|
||||
"PresignedAuth_creds_invalid_date": PresignedAuth_creds_invalid_date,
|
||||
|
||||
@@ -68,11 +68,7 @@ func Authentication_invalid_auth_header(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrMissingFields)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidAuthHeader))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -94,16 +90,117 @@ func Authentication_unsupported_signature_version(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureVersionNotSupported)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrUnsupportedAuthorizationType))
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_malformed_credentials(s *S3Conf) error {
|
||||
testName := "Authentication_malformed_credentials"
|
||||
func Authentication_missing_components(s *S3Conf) error {
|
||||
testName := "Authentication_missing_components"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
// missing SignedHeaders component
|
||||
req.Header.Set("Authorization", "AWS4-HMAC-SHA256 Credential=access/20250912/us-east-1/s3/aws4_request,Signature=5fb279ae552098ea7c5c807df54cdb159e74939e19449b29831552639ec34b29")
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.MissingComponents())
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_malformed_component(s *S3Conf) error {
|
||||
testName := "Authentication_malformed_component"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
// malformed SignedHeaders
|
||||
req.Header.Set("Authorization", "AWS4-HMAC-SHA256 Credential=access/20250912/us-east-1/s3/aws4_request,SignedHeaders-Content-Length,Signature=signature")
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.MalformedComponent("SignedHeaders-Content-Length"))
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_missing_credentials(s *S3Conf) error {
|
||||
testName := "Authentication_missing_credentials"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
// missing Credentials
|
||||
req.Header.Set("Authorization", "AWS4-HMAC-SHA256 missing_creds=access/20250912/us-east-1/s3/aws4_request,SignedHeaders=content-length;x-amz-date,Signature=5fb279ae552098ea7c5c807df54cdb159e74939e19449b29831552639ec34b29")
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.MissingCredential())
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_missing_signedheaders(s *S3Conf) error {
|
||||
testName := "Authentication_missing_signedheaders"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
// missing SignedHeaders
|
||||
req.Header.Set("Authorization", "AWS4-HMAC-SHA256 Credential=access/20250912/us-east-1/s3/aws4_request,missing=content-length;x-amz-date,Signature=5fb279ae552098ea7c5c807df54cdb159e74939e19449b29831552639ec34b29")
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.MissingSignedHeaders())
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_missing_signature(s *S3Conf) error {
|
||||
testName := "Authentication_missing_signature"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
// missing Signature
|
||||
req.Header.Set("Authorization", "AWS4-HMAC-SHA256 Credential=access/20250912/us-east-1/s3/aws4_request,SignedHeaders=content-length;x-amz-date,missing=5fb279ae552098ea7c5c807df54cdb159e74939e19449b29831552639ec34b29")
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.MissingSignature())
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_malformed_credential(s *S3Conf) error {
|
||||
testName := "Authentication_malformed_credential"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
@@ -113,7 +210,7 @@ func Authentication_malformed_credentials(s *S3Conf) error {
|
||||
}, func(req *http.Request) error {
|
||||
authHdr := req.Header.Get("Authorization")
|
||||
regExp := regexp.MustCompile("Credential=[^,]+,")
|
||||
hdr := regExp.ReplaceAllString(authHdr, "Credential-access/32234/us-east-1/s3/aws4_request,")
|
||||
hdr := regExp.ReplaceAllString(authHdr, "Credential=access/32234/us-east-1/s3/extra/things,")
|
||||
req.Header.Set("Authorization", hdr)
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
@@ -121,43 +218,12 @@ func Authentication_malformed_credentials(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrCredMalformed)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.MalformedCredential())
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_malformed_credentials_invalid_parts(s *S3Conf) error {
|
||||
testName := "Authentication_malformed_credentials_invalid_parts"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
authHdr := req.Header.Get("Authorization")
|
||||
regExp := regexp.MustCompile("Credential=[^,]+,")
|
||||
hdr := regExp.ReplaceAllString(authHdr, "Credential=access/32234/us-east-1/s3,")
|
||||
req.Header.Set("Authorization", hdr)
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrCredMalformed)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_credentials_terminated_string(s *S3Conf) error {
|
||||
testName := "Authentication_credentials_terminated_string"
|
||||
func Authentication_credentials_invalid_terminal(s *S3Conf) error {
|
||||
testName := "Authentication_credentials_invalid_terminal"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
@@ -175,11 +241,7 @@ func Authentication_credentials_terminated_string(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureTerminationStr)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.InvalidTerminal("aws_request"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -189,20 +251,20 @@ func Authentication_credentials_incorrect_service(s *S3Conf) error {
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "ec2",
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
authHdr := req.Header.Get("Authorization")
|
||||
regExp := regexp.MustCompile("Credential=[^,]+,")
|
||||
hdr := regExp.ReplaceAllString(authHdr, "Credential=access/32234/us-east-1/ec2/aws4_request,")
|
||||
req.Header.Set("Authorization", hdr)
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureIncorrService)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.IncorrectService("ec2"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -221,22 +283,12 @@ func Authentication_credentials_incorrect_region(s *S3Conf) error {
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
apiErr := s3err.APIError{
|
||||
Code: "SignatureDoesNotMatch",
|
||||
Description: fmt.Sprintf("Credential should be scoped to a valid Region, not %v", cfg.awsRegion),
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, apiErr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.IncorrectRegion(s.awsRegion, cfg.awsRegion))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -259,11 +311,7 @@ func Authentication_credentials_invalid_date(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.InvalidDateFormat("3223423234"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -360,38 +408,7 @@ func Authentication_credentials_non_existing_access_key(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidAccessKeyID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func Authentication_invalid_signed_headers(s *S3Conf) error {
|
||||
testName := "Authentication_invalid_signed_headers"
|
||||
return authHandler(s, &authConfig{
|
||||
testName: testName,
|
||||
method: http.MethodGet,
|
||||
body: nil,
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
authHdr := req.Header.Get("Authorization")
|
||||
regExp := regexp.MustCompile("SignedHeaders=[^,]+,")
|
||||
hdr := regExp.ReplaceAllString(authHdr, "SignedHeaders-host;x-amz-content-sha256;x-amz-date,")
|
||||
req.Header.Set("Authorization", hdr)
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidQueryParams)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidAccessKeyID))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -411,11 +428,7 @@ func Authentication_missing_date_header(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrMissingDateHeader)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrMissingDateHeader))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -435,11 +448,7 @@ func Authentication_invalid_date_header(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrMalformedDate)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrMissingDateHeader))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -452,18 +461,22 @@ func Authentication_date_mismatch(s *S3Conf) error {
|
||||
service: "s3",
|
||||
date: time.Now(),
|
||||
}, func(req *http.Request) error {
|
||||
req.Header.Set("X-Amz-Date", "20220830T095525Z")
|
||||
err := createUsers(s, []user{testuser1})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authHdr := req.Header.Get("Authorization")
|
||||
regExp := regexp.MustCompile("Credential=[^,]+,")
|
||||
hdr := regExp.ReplaceAllString(authHdr, "Credential=grt1/20250912/us-east-1/s3/aws4_request,")
|
||||
req.Header.Set("Authorization", hdr)
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.MalformedAuth.DateMismatch())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -483,11 +496,7 @@ func Authentication_invalid_sha256_payload_hash(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidSHA256Paylod)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidSHA256Paylod))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -508,11 +517,7 @@ func Authentication_incorrect_payload_hash(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrContentSHA256Mismatch)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrContentSHA256Mismatch))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -533,11 +538,7 @@ func Authentication_incorrect_md5(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidDigest)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidDigest))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -558,11 +559,33 @@ func Authentication_signature_error_incorrect_secret_key(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureDoesNotMatch)); err != nil {
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureDoesNotMatch))
|
||||
})
|
||||
}
|
||||
|
||||
func PresignedAuth_security_token_not_supported(s *S3Conf) error {
|
||||
testName := "PresignedAuth_security_token_not_supported"
|
||||
return presignedAuthHandler(s, testName, func(client *s3.PresignClient, bucket string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
v4req, err := client.PresignDeleteBucket(ctx, &s3.DeleteBucketInput{Bucket: &bucket})
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
uri := v4req.URL + "&X-Amz-Security-Token=my_token"
|
||||
|
||||
req, err := http.NewRequest(v4req.Method, uri, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.SecurityTokenNotSupported())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -588,11 +611,66 @@ func PresignedAuth_unsupported_algorithm(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidQuerySignatureAlgo)); err != nil {
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.UnsupportedAlgorithm())
|
||||
})
|
||||
}
|
||||
|
||||
func PresignedAuth_ECDSA_not_supported(s *S3Conf) error {
|
||||
testName := "PresignedAuth_ECDSA_not_supported"
|
||||
return presignedAuthHandler(s, testName, func(client *s3.PresignClient, bucket string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
v4req, err := client.PresignDeleteBucket(ctx, &s3.DeleteBucketInput{Bucket: &bucket})
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
uri := strings.Replace(v4req.URL, "AWS4-HMAC-SHA256", "AWS4-ECDSA-P256-SHA256", 1)
|
||||
|
||||
req, err := http.NewRequest(v4req.Method, uri, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.OnlyHMACSupported())
|
||||
})
|
||||
}
|
||||
|
||||
func PresignedAuth_missing_signature_query_param(s *S3Conf) error {
|
||||
testName := "PresignedAuth_missing_signature_query_param"
|
||||
return presignedAuthHandler(s, testName, func(client *s3.PresignClient, bucket string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
v4req, err := client.PresignDeleteBucket(ctx, &s3.DeleteBucketInput{Bucket: &bucket})
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
urlParsed, err := url.Parse(v4req.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queries := urlParsed.Query()
|
||||
queries.Del("X-Amz-Signature")
|
||||
urlParsed.RawQuery = queries.Encode()
|
||||
|
||||
req, err := http.NewRequest(v4req.Method, urlParsed.String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.MissingRequiredParams())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -625,11 +703,7 @@ func PresignedAuth_missing_credentials_query_param(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidQueryParams)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.MissingRequiredParams())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -662,16 +736,12 @@ func PresignedAuth_malformed_creds_invalid_parts(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrCredMalformed)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.MalformedCredential())
|
||||
})
|
||||
}
|
||||
|
||||
func PresignedAuth_creds_invalid_terminator(s *S3Conf) error {
|
||||
testName := "PresignedAuth_creds_invalid_terminator"
|
||||
func PresignedAuth_creds_invalid_terminal(s *S3Conf) error {
|
||||
testName := "PresignedAuth_creds_invalid_terminal"
|
||||
return presignedAuthHandler(s, testName, func(client *s3.PresignClient, bucket string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
v4req, err := client.PresignDeleteBucket(ctx, &s3.DeleteBucketInput{Bucket: &bucket})
|
||||
@@ -695,11 +765,7 @@ func PresignedAuth_creds_invalid_terminator(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureTerminationStr)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.IncorrectTerminal("aws5_request"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -728,11 +794,7 @@ func PresignedAuth_creds_incorrect_service(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureIncorrService)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.IncorrectService("sns"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -766,15 +828,7 @@ func PresignedAuth_creds_incorrect_region(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.APIError{
|
||||
Code: "SignatureDoesNotMatch",
|
||||
Description: fmt.Sprintf("Credential should be scoped to a valid Region, not %v", cfg.awsRegion),
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.IncorrectRegion(s.awsRegion, cfg.awsRegion))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -803,11 +857,7 @@ func PresignedAuth_creds_invalid_date(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.InvalidDateFormat("32234Z34"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -836,11 +886,7 @@ func PresignedAuth_non_existing_access_key_id(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidAccessKeyID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidAccessKeyID))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -873,11 +919,7 @@ func PresignedAuth_missing_date_query(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidQueryParams)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.MissingRequiredParams())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -891,6 +933,14 @@ func PresignedAuth_dates_mismatch(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
urlParsed, err := url.Parse(v4req.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tDate := urlParsed.Query().Get("X-Amz-Date")
|
||||
date := tDate[:8]
|
||||
|
||||
uri, err := changeAuthCred(v4req.URL, "20060102", credDate)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -906,11 +956,7 @@ func PresignedAuth_dates_mismatch(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrSignatureDateDoesNotMatch)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.DateMismatch("20060102", date))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -943,11 +989,7 @@ func PresignedAuth_missing_signed_headers_query_param(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidQueryParams)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.MissingRequiredParams())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -980,11 +1022,7 @@ func PresignedAuth_missing_expiration_query_param(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidQueryParams)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.MissingRequiredParams())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1017,11 +1055,7 @@ func PresignedAuth_invalid_expiration_query_param(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrMalformedExpires)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.ExpiresNumber())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1054,11 +1088,7 @@ func PresignedAuth_negative_expiration_query_param(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrNegativeExpires)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.ExpiresNegative())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1091,11 +1121,7 @@ func PresignedAuth_exceeding_expiration_query_param(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrMaximumExpires)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return checkHTTPResponseApiErr(resp, s3err.QueryAuthErrors.ExpiresTooLarge())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user