diff --git a/auth/object_lock.go b/auth/object_lock.go index 37252f02..6d070e2e 100644 --- a/auth/object_lock.go +++ b/auth/object_lock.go @@ -49,6 +49,13 @@ func ParseBucketLockConfigurationInput(input []byte) ([]byte, error) { return nil, s3err.GetAPIError(s3err.ErrMalformedXML) } + if retention.Days != nil && *retention.Days <= 0 { + return nil, s3err.GetAPIError(s3err.ErrObjectLockInvalidRetentionPeriod) + } + if retention.Years != nil && *retention.Years <= 0 { + return nil, s3err.GetAPIError(s3err.ErrObjectLockInvalidRetentionPeriod) + } + config.DefaultRetention = retention now := time.Now() config.CreatedAt = &now diff --git a/s3err/s3err.go b/s3err/s3err.go index ad493f74..cf882931 100644 --- a/s3err/s3err.go +++ b/s3err/s3err.go @@ -118,6 +118,7 @@ const ( ErrObjectLockConfigurationNotAllowed ErrObjectLocked ErrPastObjectLockRetainDate + ErrObjectLockInvalidRetentionPeriod ErrNoSuchBucketPolicy ErrBucketTaggingNotFound ErrObjectLockInvalidHeaders @@ -446,6 +447,11 @@ var errorCodeResponse = map[ErrorCode]APIError{ Description: "the retain until date must be in the future", HTTPStatusCode: http.StatusBadRequest, }, + ErrObjectLockInvalidRetentionPeriod: { + Code: "InvalidRetentionPeriod", + Description: "the retention days/years must be positive integer", + HTTPStatusCode: http.StatusBadRequest, + }, ErrNoSuchBucketPolicy: { Code: "NoSuchBucketPolicy", Description: "The bucket policy does not exist", diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 13dea4bc..2a93eaf3 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -312,6 +312,7 @@ func TestPutObjectLockConfiguration(s *S3Conf) { PutObjectLockConfiguration_empty_config(s) PutObjectLockConfiguration_not_enabled_on_bucket_creation(s) PutObjectLockConfiguration_both_years_and_days(s) + PutObjectLockConfiguration_invalid_years_days(s) PutObjectLockConfiguration_success(s) } @@ -631,6 +632,7 @@ func GetIntTests() IntTests { "PutObjectLockConfiguration_empty_config": PutObjectLockConfiguration_empty_config, "PutObjectLockConfiguration_not_enabled_on_bucket_creation": PutObjectLockConfiguration_not_enabled_on_bucket_creation, "PutObjectLockConfiguration_both_years_and_days": PutObjectLockConfiguration_both_years_and_days, + "PutObjectLockConfiguration_invalid_years_days": PutObjectLockConfiguration_invalid_years_days, "PutObjectLockConfiguration_success": PutObjectLockConfiguration_success, "GetObjectLockConfiguration_non_existing_bucket": GetObjectLockConfiguration_non_existing_bucket, "GetObjectLockConfiguration_unset_config": GetObjectLockConfiguration_unset_config, diff --git a/tests/integration/tests.go b/tests/integration/tests.go index 12006b5e..0efdbaf2 100644 --- a/tests/integration/tests.go +++ b/tests/integration/tests.go @@ -6392,6 +6392,47 @@ func PutObjectLockConfiguration_both_years_and_days(s *S3Conf) error { }) } +func PutObjectLockConfiguration_invalid_years_days(s *S3Conf) error { + testName := "PutObjectLockConfiguration_invalid_years" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + var days, years int32 = -3, -5 + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.PutObjectLockConfiguration(ctx, &s3.PutObjectLockConfigurationInput{ + Bucket: &bucket, + ObjectLockConfiguration: &types.ObjectLockConfiguration{ + ObjectLockEnabled: types.ObjectLockEnabledEnabled, + Rule: &types.ObjectLockRule{ + DefaultRetention: &types.DefaultRetention{ + Days: &days, + }, + }, + }, + }) + cancel() + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrObjectLockInvalidRetentionPeriod)); err != nil { + return err + } + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) + _, err = s3client.PutObjectLockConfiguration(ctx, &s3.PutObjectLockConfigurationInput{ + Bucket: &bucket, + ObjectLockConfiguration: &types.ObjectLockConfiguration{ + ObjectLockEnabled: types.ObjectLockEnabledEnabled, + Rule: &types.ObjectLockRule{ + DefaultRetention: &types.DefaultRetention{ + Years: &years, + }, + }, + }, + }) + cancel() + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrObjectLockInvalidRetentionPeriod)); err != nil { + return err + } + + return nil + }) +} + func PutObjectLockConfiguration_success(s *S3Conf) error { testName := "PutObjectLockConfiguration_success" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {