fix: fixes invalid/expired x-amz-object-lock-retain-until-date errors

Fixes #1733
Fixes #1734

The `x-amz-object-lock-retain-until-date` request header appears in the `PutObject`, `CopyObject`, and `CreateMultipartUpload` operations. This PR fixes the two types of error codes and messages returned when the header value is invalid or expired and adds the corresponding integration tests.
This commit is contained in:
niksis02
2026-01-09 17:13:02 +04:00
parent f2a75708e4
commit cf99b3e036
4 changed files with 60 additions and 3 deletions
+1 -1
View File
@@ -355,7 +355,7 @@ func ParsObjectLockHdrs(ctx *fiber.Ctx) (*objLockCfg, error) {
rDate, err := time.Parse(time.RFC3339, objLockDate)
if err != nil {
debuglogger.Logf("failed to parse retain until date: %v\n", err)
return nil, s3err.GetAPIError(s3err.ErrInvalidRequest)
return nil, s3err.GetAPIError(s3err.ErrInvalidRetainUntilDate)
}
if rDate.Before(time.Now()) {
debuglogger.Logf("expired retain until date: %v\n", rDate.Format(time.RFC3339))
+8 -2
View File
@@ -141,6 +141,7 @@ const (
ErrInvalidBucketObjectLockConfiguration
ErrObjectLockConfigurationNotAllowed
ErrObjectLocked
ErrInvalidRetainUntilDate
ErrPastObjectLockRetainDate
ErrObjectLockInvalidRetentionPeriod
ErrInvalidLegalHoldStatus
@@ -613,9 +614,14 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "Access Denied because object protected by object lock.",
HTTPStatusCode: http.StatusForbidden,
},
ErrInvalidRetainUntilDate: {
Code: "InvalidArgument",
Description: "The retain until date must be provided in ISO 8601 format",
HTTPStatusCode: http.StatusBadRequest,
},
ErrPastObjectLockRetainDate: {
Code: "InvalidRequest",
Description: "the retain until date must be in the future.",
Code: "InvalidArgument",
Description: "The retain until date must be in the future!",
HTTPStatusCode: http.StatusBadRequest,
},
ErrObjectLockInvalidRetentionPeriod: {
+47
View File
@@ -18,6 +18,7 @@ import (
"bytes"
"context"
"fmt"
"net/http"
"strings"
"time"
@@ -299,6 +300,52 @@ func PutObject_invalid_object_lock_mode(s *S3Conf) error {
}, withLock())
}
func PutObject_past_retain_until_date(s *S3Conf) error {
testName := "PutObject_past_retain_until_date"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
rDate := time.Now().AddDate(-1, 0, 0)
_, err := putObjectWithData(10, &s3.PutObjectInput{
Bucket: &bucket,
Key: getPtr("my-object"),
ObjectLockMode: types.ObjectLockModeGovernance,
ObjectLockRetainUntilDate: &rDate,
}, s3client)
return checkApiErr(err, s3err.GetAPIError(s3err.ErrPastObjectLockRetainDate))
}, withLock())
}
func PutObject_invalid_retain_until_date(s *S3Conf) error {
testName := "PutObject_invalid_retain_until_date"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
req, err := createSignedReq(
http.MethodPut,
s.endpoint,
fmt.Sprintf("%s/my-object", bucket),
s.awsID,
s.awsSecret,
"s3",
s.awsRegion,
nil,
time.Now(),
map[string]string{
"x-amz-object-lock-retain-until-date": "invalid_date",
"x-amz-object-lock-mode": "GOVERNANCE",
},
)
if err != nil {
return err
}
resp, err := s.httpClient.Do(req)
if err != nil {
return err
}
return checkHTTPResponseApiErr(resp, s3err.GetAPIError(s3err.ErrInvalidRetainUntilDate))
}, withLock())
}
func PutObject_conditional_writes(s *S3Conf) error {
testName := "PutObject_conditional_writes"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
+4
View File
@@ -165,6 +165,8 @@ func TestPutObject(ts *TestState) {
ts.Run(PutObject_with_object_lock)
ts.Run(PutObject_invalid_legal_hold)
ts.Run(PutObject_invalid_object_lock_mode)
ts.Run(PutObject_past_retain_until_date)
ts.Run(PutObject_invalid_retain_until_date)
ts.Run(PutObject_conditional_writes)
//TODO: remove the condition after implementing checksums in azure
if !ts.conf.azureTests {
@@ -1194,6 +1196,8 @@ func GetIntTests() IntTests {
"PutObject_with_object_lock": PutObject_with_object_lock,
"PutObject_invalid_legal_hold": PutObject_invalid_legal_hold,
"PutObject_invalid_object_lock_mode": PutObject_invalid_object_lock_mode,
"PutObject_past_retain_until_date": PutObject_past_retain_until_date,
"PutObject_invalid_retain_until_date": PutObject_invalid_retain_until_date,
"PutObject_conditional_writes": PutObject_conditional_writes,
"PutObject_with_metadata": PutObject_with_metadata,
"PutObject_invalid_credentials": PutObject_invalid_credentials,