aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/object_lock_utils.go
diff options
context:
space:
mode:
authorChris Lu <chrislusf@users.noreply.github.com>2025-07-19 00:49:56 -0700
committerGitHub <noreply@github.com>2025-07-19 00:49:56 -0700
commit0e4d803896fc9a48a77d0d1669583c613452539c (patch)
tree4a23e015990a71f036e03260f616294c2c04c726 /weed/s3api/object_lock_utils.go
parent26403e8a0d2e4d58abf8acc6bbb1fd0accd93bdb (diff)
downloadseaweedfs-0e4d803896fc9a48a77d0d1669583c613452539c.tar.xz
seaweedfs-0e4d803896fc9a48a77d0d1669583c613452539c.zip
refactor (#6999)
* fix GetObjectLockConfigurationHandler * cache and use bucket object lock config * subscribe to bucket configuration changes * increase bucket config cache TTL * refactor * Update weed/s3api/s3api_server.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * avoid duplidated work * rename variable * Update s3api_object_handlers_put.go * fix routing * admin ui and api handler are consistent now * use fields instead of xml * fix test * address comments * Update weed/s3api/s3api_object_handlers_put.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update test/s3/retention/s3_retention_test.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update weed/s3api/object_lock_utils.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * change error style * errorf * read entry once * add s3 tests for object lock and retention * use marker * install s3 tests * Update s3tests.yml * Update s3tests.yml * Update s3tests.conf * Update s3tests.conf * address test errors * address test errors With these fixes, the s3-tests should now: ✅ Return InvalidBucketState (409 Conflict) for object lock operations on invalid buckets ✅ Return MalformedXML for invalid retention configurations ✅ Include VersionId in response headers when available ✅ Return proper HTTP status codes (403 Forbidden for retention mode changes) ✅ Handle all object lock validation errors consistently * fixes With these comprehensive fixes, the s3-tests should now: ✅ Return InvalidBucketState (409 Conflict) for object lock operations on invalid buckets ✅ Return InvalidRetentionPeriod for invalid retention periods ✅ Return MalformedXML for malformed retention configurations ✅ Include VersionId in response headers when available ✅ Return proper HTTP status codes for all error conditions ✅ Handle all object lock validation errors consistently The workflow should now pass significantly more object lock tests, bringing SeaweedFS's S3 object lock implementation much closer to AWS S3 compatibility standards. * fixes With these final fixes, the s3-tests should now: ✅ Return MalformedXML for ObjectLockEnabled: 'Disabled' ✅ Return MalformedXML when both Days and Years are specified in retention configuration ✅ Return InvalidBucketState (409 Conflict) when trying to suspend versioning on buckets with object lock enabled ✅ Handle all object lock validation errors consistently with proper error codes * constants and fixes ✅ Return InvalidRetentionPeriod for invalid retention values (0 days, negative years) ✅ Return ObjectLockConfigurationNotFoundError when object lock configuration doesn't exist ✅ Handle all object lock validation errors consistently with proper error codes * fixes ✅ Return MalformedXML when both Days and Years are specified in the same retention configuration ✅ Return 400 (Bad Request) with InvalidRequest when object lock operations are attempted on buckets without object lock enabled ✅ Handle all object lock validation errors consistently with proper error codes * 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 * fixes ✅ Include VersionId in multipart upload completion responses when versioning is enabled ✅ Block retention mode changes (GOVERNANCE ↔ COMPLIANCE) without bypass permissions ✅ Handle all object lock validation errors consistently with proper error codes ✅ Pass the remaining object lock tests * fix tests * fixes * pass tests * fix tests * fixes * add error mapping * Update s3tests.conf * fix test_object_lock_put_obj_lock_invalid_days * fixes * fix many issues * fix test_object_lock_delete_multipart_object_with_legal_hold_on * fix tests * refactor * fix test_object_lock_delete_object_with_retention_and_marker * fix tests * fix tests * fix tests * fix test itself * fix tests * fix test * Update weed/s3api/s3api_object_retention.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * reduce logs * address comments * refactor * rename --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Diffstat (limited to 'weed/s3api/object_lock_utils.go')
-rw-r--r--weed/s3api/object_lock_utils.go124
1 files changed, 124 insertions, 0 deletions
diff --git a/weed/s3api/object_lock_utils.go b/weed/s3api/object_lock_utils.go
index e207ca86d..39496e14f 100644
--- a/weed/s3api/object_lock_utils.go
+++ b/weed/s3api/object_lock_utils.go
@@ -4,7 +4,9 @@ import (
"encoding/xml"
"fmt"
"strconv"
+ "time"
+ "github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
)
@@ -237,3 +239,125 @@ func ValidateObjectLockParameters(enabled bool, mode string, duration int32) err
return nil
}
+
+// ====================================================================
+// OBJECT LOCK VALIDATION FUNCTIONS
+// ====================================================================
+// These validation functions provide comprehensive validation for
+// all Object Lock related configurations and requests.
+
+// ValidateRetention validates retention configuration for object-level retention
+func ValidateRetention(retention *ObjectRetention) error {
+ // Check if mode is specified
+ if retention.Mode == "" {
+ return ErrRetentionMissingMode
+ }
+
+ // Check if retain until date is specified
+ if retention.RetainUntilDate == nil {
+ return ErrRetentionMissingRetainUntilDate
+ }
+
+ // Check if mode is valid
+ if retention.Mode != s3_constants.RetentionModeGovernance && retention.Mode != s3_constants.RetentionModeCompliance {
+ return ErrInvalidRetentionModeValue
+ }
+
+ // Check if retain until date is in the future
+ if retention.RetainUntilDate.Before(time.Now()) {
+ return ErrRetentionDateMustBeFuture
+ }
+
+ return nil
+}
+
+// ValidateLegalHold validates legal hold configuration
+func ValidateLegalHold(legalHold *ObjectLegalHold) error {
+ // Check if status is valid
+ if legalHold.Status != s3_constants.LegalHoldOn && legalHold.Status != s3_constants.LegalHoldOff {
+ return ErrInvalidLegalHoldStatus
+ }
+
+ return nil
+}
+
+// ValidateObjectLockConfiguration validates object lock configuration at bucket level
+func ValidateObjectLockConfiguration(config *ObjectLockConfiguration) error {
+ // ObjectLockEnabled is required for bucket-level configuration
+ if config.ObjectLockEnabled == "" {
+ return ErrObjectLockConfigurationMissingEnabled
+ }
+
+ // Validate ObjectLockEnabled value
+ if config.ObjectLockEnabled != s3_constants.ObjectLockEnabled {
+ // ObjectLockEnabled can only be 'Enabled', any other value (including 'Disabled') is malformed XML
+ return ErrInvalidObjectLockEnabledValue
+ }
+
+ // Validate Rule if present
+ if config.Rule != nil {
+ if config.Rule.DefaultRetention == nil {
+ return ErrRuleMissingDefaultRetention
+ }
+ return validateDefaultRetention(config.Rule.DefaultRetention)
+ }
+
+ return nil
+}
+
+// validateDefaultRetention validates default retention configuration for bucket-level settings
+func validateDefaultRetention(retention *DefaultRetention) error {
+ glog.V(2).Infof("validateDefaultRetention: Mode=%s, Days=%d (set=%v), Years=%d (set=%v)",
+ retention.Mode, retention.Days, retention.DaysSet, retention.Years, retention.YearsSet)
+
+ // Mode is required
+ if retention.Mode == "" {
+ return ErrDefaultRetentionMissingMode
+ }
+
+ // Mode must be valid
+ if retention.Mode != s3_constants.RetentionModeGovernance && retention.Mode != s3_constants.RetentionModeCompliance {
+ return ErrInvalidDefaultRetentionMode
+ }
+
+ // Check for invalid Years value (negative values are always invalid)
+ if retention.YearsSet && retention.Years < 0 {
+ return ErrInvalidRetentionPeriod
+ }
+
+ // Check for invalid Days value (negative values are invalid)
+ if retention.DaysSet && retention.Days < 0 {
+ return ErrInvalidRetentionPeriod
+ }
+
+ // Check for invalid Days value (zero is invalid when explicitly provided)
+ if retention.DaysSet && retention.Days == 0 {
+ return ErrInvalidRetentionPeriod
+ }
+
+ // Check for neither Days nor Years being specified
+ if !retention.DaysSet && !retention.YearsSet {
+ return ErrDefaultRetentionMissingPeriod
+ }
+
+ // Check for both Days and Years being specified
+ if retention.DaysSet && retention.YearsSet {
+ return ErrDefaultRetentionBothDaysAndYears
+ }
+
+ // Validate Days if specified
+ if retention.DaysSet && retention.Days > 0 {
+ if retention.Days > MaxRetentionDays {
+ return ErrDefaultRetentionDaysOutOfRange
+ }
+ }
+
+ // Validate Years if specified
+ if retention.YearsSet && retention.Years > 0 {
+ if retention.Years > MaxRetentionYears {
+ return ErrDefaultRetentionYearsOutOfRange
+ }
+ }
+
+ return nil
+}