Merge pull request #1744 from versity/sis/invalid-retain-until-date-header-err

fix: fixes invalid/expired x-amz-object-lock-retain-until-date errors
This commit is contained in:
Ben McClelland
2026-01-09 15:33:30 -08:00
committed by GitHub
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,