aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchrislu <chris.lu@gmail.com>2025-07-18 16:11:14 -0700
committerchrislu <chris.lu@gmail.com>2025-07-18 16:11:14 -0700
commiteaaef569cedd0063c990acad7693cf1d43cfce28 (patch)
treee3391944966a842e6208fccfe2967cab28909241
parent1807f4e94d3ebe8ae91f59fc34d49cd5795ac891 (diff)
downloadseaweedfs-eaaef569cedd0063c990acad7693cf1d43cfce28.tar.xz
seaweedfs-eaaef569cedd0063c990acad7693cf1d43cfce28.zip
fixes
✅ Return 409 (Conflict) with InvalidBucketState for bucket-level object lock configuration operations on buckets without object lock enabled ✅ Allow increasing retention periods and overriding retention with same/later dates ✅ Only block decreasing retention periods without proper bypass permissions ✅ Handle all object lock validation errors consistently with proper error codes
-rw-r--r--weed/s3api/s3api_bucket_handlers_object_lock_config.go13
-rw-r--r--weed/s3api/s3api_object_retention.go24
2 files changed, 28 insertions, 9 deletions
diff --git a/weed/s3api/s3api_bucket_handlers_object_lock_config.go b/weed/s3api/s3api_bucket_handlers_object_lock_config.go
index 2c4be3b33..9ff12a086 100644
--- a/weed/s3api/s3api_bucket_handlers_object_lock_config.go
+++ b/weed/s3api/s3api_bucket_handlers_object_lock_config.go
@@ -4,6 +4,8 @@ import (
"encoding/xml"
"net/http"
+ "errors"
+
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
@@ -17,7 +19,16 @@ func (s3a *S3ApiServer) PutObjectLockConfigurationHandler(w http.ResponseWriter,
glog.V(3).Infof("PutObjectLockConfigurationHandler %s", bucket)
// Check if Object Lock is available for this bucket (requires versioning)
- if !s3a.handleObjectLockAvailabilityCheck(w, r, bucket, "PutObjectLockConfigurationHandler") {
+ // For bucket-level operations, return InvalidBucketState (409) when object lock is not available
+ if err := s3a.isObjectLockAvailable(bucket); err != nil {
+ glog.Errorf("PutObjectLockConfigurationHandler: object lock not available for bucket %s: %v", bucket, err)
+ if errors.Is(err, ErrBucketNotFound) {
+ s3err.WriteErrorResponse(w, r, s3err.ErrNoSuchBucket)
+ } else {
+ // Return InvalidBucketState for bucket-level object lock operations on buckets without object lock enabled
+ // This matches AWS S3 behavior and s3-tests expectations (409 Conflict)
+ s3err.WriteErrorResponse(w, r, s3err.ErrInvalidBucketState)
+ }
return
}
diff --git a/weed/s3api/s3api_object_retention.go b/weed/s3api/s3api_object_retention.go
index f0adb28fd..671ab0858 100644
--- a/weed/s3api/s3api_object_retention.go
+++ b/weed/s3api/s3api_object_retention.go
@@ -348,18 +348,26 @@ func (s3a *S3ApiServer) setObjectRetention(bucket, object, versionId string, ret
// Check if object is already under retention
if entry.Extended != nil {
if existingMode, exists := entry.Extended[s3_constants.ExtObjectLockModeKey]; exists {
- if string(existingMode) == s3_constants.RetentionModeCompliance && !bypassGovernance {
- // Return 403 Forbidden for compliance mode changes without bypass
- return ErrComplianceModeActive
- }
-
if existingDateBytes, dateExists := entry.Extended[s3_constants.ExtRetentionUntilDateKey]; dateExists {
if timestamp, err := strconv.ParseInt(string(existingDateBytes), 10, 64); err == nil {
existingDate := time.Unix(timestamp, 0)
- if existingDate.After(time.Now()) && string(existingMode) == s3_constants.RetentionModeGovernance && !bypassGovernance {
- // Return 403 Forbidden for governance mode changes without bypass
- return ErrGovernanceModeActive
+
+ // Check if the new retention date is earlier than the existing one
+ if retention.RetainUntilDate != nil && retention.RetainUntilDate.Before(existingDate) {
+ // Attempting to decrease retention period
+ if string(existingMode) == s3_constants.RetentionModeCompliance {
+ // Cannot decrease compliance mode retention without bypass
+ return ErrComplianceModeActive
+ }
+
+ if string(existingMode) == s3_constants.RetentionModeGovernance && !bypassGovernance {
+ // Cannot decrease governance mode retention without bypass
+ return ErrGovernanceModeActive
+ }
}
+
+ // If new retention date is later or same, allow the operation
+ // This covers both increasing retention period and overriding with same/later date
}
}
}