fix: reject an empty start-after and continuation-token in ListObjects (V1)
This commit is contained in:
1 parent
613c71290f
commit
276128b42b
4 files changed
+74
-7
No files matched your search
@@ -615,8 +615,17 @@ func (c S3ApiController) ListObjects(ctx fiber.Ctx) (*Response, error) {
|
||||
region = defaultRegion
|
||||
}
|
||||
|
||||
// start-after is a ListObjectsV2 argument, S3 rejects it on a V1 listing
|
||||
if ctx.Query("start-after") != "" {
|
||||
// continuation-token and start-after are ListObjectsV2 arguments, S3
|
||||
// rejects either one on a V1 listing, with or without a value
|
||||
queryArgs := ctx.Request().URI().QueryArgs()
|
||||
if queryArgs.Has("continuation-token") {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
},
|
||||
}, s3err.GetInvalidArgumentErr(s3err.InvalidArgContinuationToken, "")
|
||||
}
|
||||
if queryArgs.Has("start-after") {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
|
||||
@@ -1213,6 +1213,42 @@ func TestS3ApiController_ListObjects(t *testing.T) {
|
||||
err: s3err.GetInvalidArgumentErr(s3err.InvalidArgStartAfter, ""),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty start-after is not supported",
|
||||
input: testInput{
|
||||
locals: defaultLocals,
|
||||
beRes: listResult,
|
||||
queries: map[string]string{
|
||||
"start-after": "",
|
||||
},
|
||||
},
|
||||
output: testOutput{
|
||||
response: &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: "root",
|
||||
},
|
||||
},
|
||||
err: s3err.GetInvalidArgumentErr(s3err.InvalidArgStartAfter, ""),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "continuation-token is not supported",
|
||||
input: testInput{
|
||||
locals: defaultLocals,
|
||||
beRes: listResult,
|
||||
queries: map[string]string{
|
||||
"continuation-token": "my-token",
|
||||
},
|
||||
},
|
||||
output: testOutput{
|
||||
response: &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: "root",
|
||||
},
|
||||
},
|
||||
err: s3err.GetInvalidArgumentErr(s3err.InvalidArgContinuationToken, ""),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid max keys",
|
||||
input: testInput{
|
||||
|
||||
@@ -27,6 +27,7 @@ const (
|
||||
InvalidArgMaxBuckets InvalidArgErrorCode = iota
|
||||
InvalidArgNegativeMaxKeys
|
||||
InvalidArgStartAfter
|
||||
InvalidArgContinuationToken
|
||||
InvalidArgObjectAttributes
|
||||
InvalidArgPartNumber
|
||||
InvalidArgCompleteMpPartNumber
|
||||
@@ -95,6 +96,10 @@ var invalidArgErrResponses = map[InvalidArgErrorCode]InvalidArgumentError{
|
||||
Description: "startAfter only supported in REST.GET.BUCKET with list-type=2",
|
||||
ArgumentName: "start-after",
|
||||
},
|
||||
InvalidArgContinuationToken: {
|
||||
Description: "continuation-token only supported in REST.GET.BUCKET with list-type=2",
|
||||
ArgumentName: "continuation-token",
|
||||
},
|
||||
InvalidArgObjectAttributes: {
|
||||
Description: "Invalid attribute name specified.",
|
||||
ArgumentName: "x-amz-object-attributes",
|
||||
|
||||
@@ -195,9 +195,9 @@ func ListObjects_invalid_max_keys(s *S3Conf) error {
|
||||
})
|
||||
}
|
||||
|
||||
// start-after belongs to ListObjectsV2, so S3 rejects it on a V1 listing
|
||||
// instead of ignoring it. The SDK ListObjects input has no StartAfter field,
|
||||
// so the request is signed and sent by hand.
|
||||
// start-after and continuation-token belong to ListObjectsV2, so S3 rejects
|
||||
// either one on a V1 listing, with or without a value. The SDK ListObjects
|
||||
// input has neither field, so the requests are signed and sent by hand.
|
||||
func ListObjects_start_after(s *S3Conf) error {
|
||||
testName := "ListObjects_start_after"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
@@ -206,8 +206,20 @@ func ListObjects_start_after(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
startAfterErr := s3err.GetInvalidArgumentErr(s3err.InvalidArgStartAfter, "")
|
||||
contTokenErr := s3err.GetInvalidArgumentErr(s3err.InvalidArgContinuationToken, "")
|
||||
for _, test := range []struct {
|
||||
query string
|
||||
expected s3err.S3Error
|
||||
}{
|
||||
{"start-after=bar", startAfterErr},
|
||||
{"start-after=", startAfterErr},
|
||||
{"start-after", startAfterErr},
|
||||
{"continuation-token=bar", contTokenErr},
|
||||
{"continuation-token=", contTokenErr},
|
||||
} {
|
||||
req, err := createSignedReq(http.MethodGet, s.endpoint,
|
||||
fmt.Sprintf("%v?start-after=bar", bucket),
|
||||
fmt.Sprintf("%v?%v", bucket, test.query),
|
||||
s.awsID, s.awsSecret, "s3", s.awsRegion, "", nil, time.Now(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -218,7 +230,12 @@ func ListObjects_start_after(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return checkHTTPResponseApiErr(resp, s3err.GetInvalidArgumentErr(s3err.InvalidArgStartAfter, ""))
|
||||
if err := checkHTTPResponseApiErr(resp, test.expected); err != nil {
|
||||
return fmt.Errorf("%v: %w", test.query, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user