diff --git a/cmd/api-errors.go b/cmd/api-errors.go index 0e6cec8ba..30b0bf5b0 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -1810,7 +1810,7 @@ func toAPIError(ctx context.Context, err error) APIError { } case tagging.Error: apiErr = APIError{ - Code: "InvalidTag", + Code: e.Code(), Description: e.Error(), HTTPStatusCode: http.StatusBadRequest, } diff --git a/mint/run/core/aws-sdk-go/quick-tests.go b/mint/run/core/aws-sdk-go/quick-tests.go index daf4caa42..8c4499ff9 100644 --- a/mint/run/core/aws-sdk-go/quick-tests.go +++ b/mint/run/core/aws-sdk-go/quick-tests.go @@ -607,6 +607,200 @@ func testObjectTagging(s3Client *s3.S3) { failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUTObjectTagging input did not match with GetObjectTagging output %v", nil), nil).Fatal() return } + successLogger(function, args, startTime).Info() +} + +func testObjectTaggingErrors(s3Client *s3.S3) { + startTime := time.Now() + function := "testObjectTagging" + bucket := randString(60, rand.NewSource(time.Now().UnixNano()), "aws-sdk-go-test-") + object := randString(60, rand.NewSource(time.Now().UnixNano()), "") + args := map[string]interface{}{ + "bucketName": bucket, + "objectName": object, + } + + _, err := s3Client.CreateBucket(&s3.CreateBucketInput{ + Bucket: aws.String(bucket), + }) + if err != nil { + failureLog(function, args, startTime, "", "AWS SDK Go CreateBucket Failed", err).Fatal() + return + } + defer cleanup(s3Client, bucket, object, function, args, startTime, true) + + _, err = s3Client.PutObject(&s3.PutObjectInput{ + Body: aws.ReadSeekCloser(strings.NewReader("testfile")), + Bucket: aws.String(bucket), + Key: aws.String(object), + }) + + if err != nil { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to success but got %v", err), err).Fatal() + return + } + + // case 1 : Too many tags > 10 + input := &s3.PutObjectTaggingInput{ + Bucket: aws.String(bucket), + Key: aws.String(object), + Tagging: &s3.Tagging{ + TagSet: []*s3.Tag{ + { + Key: aws.String("Key1"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key2"), + Value: aws.String("Value4"), + }, + { + Key: aws.String("Key3"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key4"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key5"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key6"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key7"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key8"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key9"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key10"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key11"), + Value: aws.String("Value3"), + }, + }, + }, + } + + _, err = s3Client.PutObjectTagging(input) + if err == nil { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but succeeded"), err).Fatal() + return + } + + if aerr, ok := err.(awserr.Error); ok { + if aerr.Code() != "BadRequest" && aerr.Message() != "BadRequest: Object tags cannot be greater than 10" { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but got %v", err), err).Fatal() + return + } + } + + // case 2 : Duplicate Tag Keys + input = &s3.PutObjectTaggingInput{ + Bucket: aws.String(bucket), + Key: aws.String(object), + Tagging: &s3.Tagging{ + TagSet: []*s3.Tag{ + { + Key: aws.String("Key1"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key1"), + Value: aws.String("Value4"), + }, + }, + }, + } + + _, err = s3Client.PutObjectTagging(input) + if err == nil { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but succeeded"), err).Fatal() + return + } + + if aerr, ok := err.(awserr.Error); ok { + if aerr.Code() != "InvalidTag" && aerr.Message() != "InvalidTag: Cannot provide multiple Tags with the same key" { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but got %v", err), err).Fatal() + return + } + } + + // case 3 : Too long Tag Key + input = &s3.PutObjectTaggingInput{ + Bucket: aws.String(bucket), + Key: aws.String(object), + Tagging: &s3.Tagging{ + TagSet: []*s3.Tag{ + { + Key: aws.String("Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1"), + Value: aws.String("Value3"), + }, + { + Key: aws.String("Key1"), + Value: aws.String("Value4"), + }, + }, + }, + } + + _, err = s3Client.PutObjectTagging(input) + if err == nil { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but succeeded"), err).Fatal() + return + } + + if aerr, ok := err.(awserr.Error); ok { + if aerr.Code() != "InvalidTag" && aerr.Message() != "InvalidTag: The TagKey you have provided is invalid" { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but got %v", err), err).Fatal() + return + } + } + + // case 4 : Too long Tag value + input = &s3.PutObjectTaggingInput{ + Bucket: aws.String(bucket), + Key: aws.String(object), + Tagging: &s3.Tagging{ + TagSet: []*s3.Tag{ + { + Key: aws.String("Key1"), + Value: aws.String("Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1Key1"), + }, + { + Key: aws.String("Key1"), + Value: aws.String("Value4"), + }, + }, + }, + } + + _, err = s3Client.PutObjectTagging(input) + if err == nil { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but succeeded"), err).Fatal() + return + } + + if aerr, ok := err.(awserr.Error); ok { + if aerr.Code() != "InvalidTag" && aerr.Message() != "InvalidTag: The TagValue you have provided is invalid" { + failureLog(function, args, startTime, "", fmt.Sprintf("AWS SDK Go PUT expected to fail but got %v", err), err).Fatal() + return + } + } + + successLogger(function, args, startTime).Info() } // Tests bucket re-create errors. @@ -853,5 +1047,6 @@ func main() { } if isObjectTaggingImplemented(s3Client) { testObjectTagging(s3Client) + testObjectTaggingErrors(s3Client) } } diff --git a/pkg/bucket/object/tagging/error.go b/pkg/bucket/object/tagging/error.go index 42d0b75e0..89c4fab81 100644 --- a/pkg/bucket/object/tagging/error.go +++ b/pkg/bucket/object/tagging/error.go @@ -23,13 +23,14 @@ import ( // Error is the generic type for any error happening during tag // parsing. type Error struct { - err error + err error + code string } // Errorf - formats according to a format specifier and returns // the string as a value that satisfies error of type tagging.Error -func Errorf(format string, a ...interface{}) error { - return Error{err: fmt.Errorf(format, a...)} +func Errorf(format, code string, a ...interface{}) error { + return Error{err: fmt.Errorf(format, a...), code: code} } // Unwrap the internal error. @@ -42,3 +43,11 @@ func (e Error) Error() string { } return e.err.Error() } + +// Code returns appropriate error code. +func (e Error) Code() string { + if e.code == "" { + return "BadRequest" + } + return e.code +} diff --git a/pkg/bucket/object/tagging/tagging.go b/pkg/bucket/object/tagging/tagging.go index e9cbb5054..2b9b69560 100644 --- a/pkg/bucket/object/tagging/tagging.go +++ b/pkg/bucket/object/tagging/tagging.go @@ -33,10 +33,10 @@ const ( // errors returned by tagging package var ( - ErrTooManyTags = Errorf("Cannot have more than 10 object tags") - ErrInvalidTagKey = Errorf("The TagKey you have provided is invalid") - ErrInvalidTagValue = Errorf("The TagValue you have provided is invalid") - ErrInvalidTag = Errorf("Cannot provide multiple Tags with the same key") + ErrTooManyTags = Errorf("Object tags cannot be greater than 10", "BadRequest") + ErrInvalidTagKey = Errorf("The TagKey you have provided is invalid", "InvalidTag") + ErrInvalidTagValue = Errorf("The TagValue you have provided is invalid", "InvalidTag") + ErrInvalidTag = Errorf("Cannot provide multiple Tags with the same key", "InvalidTag") ) // Tagging - object tagging interface @@ -51,15 +51,15 @@ func (t Tagging) Validate() error { if len(t.TagSet.Tags) > maxTags { return ErrTooManyTags } - if t.TagSet.ContainsDuplicateTag() { - return ErrInvalidTag - } // Validate all the rules in the tagging config for _, ts := range t.TagSet.Tags { if err := ts.Validate(); err != nil { return err } } + if t.TagSet.ContainsDuplicateTag() { + return ErrInvalidTag + } return nil }