diff options
| author | chrislu <chris.lu@gmail.com> | 2025-07-18 16:11:14 -0700 |
|---|---|---|
| committer | chrislu <chris.lu@gmail.com> | 2025-07-18 16:11:14 -0700 |
| commit | eaaef569cedd0063c990acad7693cf1d43cfce28 (patch) | |
| tree | e3391944966a842e6208fccfe2967cab28909241 | |
| parent | 1807f4e94d3ebe8ae91f59fc34d49cd5795ac891 (diff) | |
| download | seaweedfs-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.go | 13 | ||||
| -rw-r--r-- | weed/s3api/s3api_object_retention.go | 24 |
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 } } } |
