mirror of
https://github.com/versity/versitygw.git
synced 2026-01-08 04:35:15 +00:00
Merge pull request #568 from versity/fix/555-put-object-lock-config-disabled
PutObjectLockConfiguration default disabled object lock
This commit is contained in:
@@ -951,6 +951,20 @@ func (az *Azure) PutObjectLockConfiguration(ctx context.Context, bucket string,
|
||||
return azureErrToS3Err(err)
|
||||
}
|
||||
|
||||
cfg, exists := props.Metadata[string(keyBucketLock)]
|
||||
if !exists {
|
||||
return s3err.GetAPIError(s3err.ErrObjectLockConfigurationNotAllowed)
|
||||
}
|
||||
|
||||
var bucketLockCfg auth.BucketLockConfig
|
||||
if err := json.Unmarshal([]byte(*cfg), &bucketLockCfg); err != nil {
|
||||
return fmt.Errorf("unmarshal object lock config: %w", err)
|
||||
}
|
||||
|
||||
if !bucketLockCfg.Enabled {
|
||||
return s3err.GetAPIError(s3err.ErrObjectLockConfigurationNotAllowed)
|
||||
}
|
||||
|
||||
props.Metadata[string(keyBucketLock)] = backend.GetStringPtr(string(config))
|
||||
|
||||
_, err = client.SetMetadata(ctx, &container.SetMetadataOptions{
|
||||
|
||||
@@ -2207,6 +2207,23 @@ func (p *Posix) PutObjectLockConfiguration(_ context.Context, bucket string, con
|
||||
return fmt.Errorf("stat bucket: %w", err)
|
||||
}
|
||||
|
||||
cfg, err := p.meta.RetrieveAttribute(bucket, "", bucketLockKey)
|
||||
if errors.Is(err, meta.ErrNoSuchKey) {
|
||||
return s3err.GetAPIError(s3err.ErrObjectLockConfigurationNotAllowed)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("get object lock config: %w", err)
|
||||
}
|
||||
|
||||
var bucketLockCfg auth.BucketLockConfig
|
||||
if err := json.Unmarshal(cfg, &bucketLockCfg); err != nil {
|
||||
return fmt.Errorf("unmarshal object lock config: %w", err)
|
||||
}
|
||||
|
||||
if !bucketLockCfg.Enabled {
|
||||
return s3err.GetAPIError(s3err.ErrObjectLockConfigurationNotAllowed)
|
||||
}
|
||||
|
||||
if err := p.meta.StoreAttribute(bucket, "", bucketLockKey, config); err != nil {
|
||||
return fmt.Errorf("set object lock config: %w", err)
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ const (
|
||||
ErrObjectLockConfigurationNotFound
|
||||
ErrNoSuchObjectLockConfiguration
|
||||
ErrInvalidBucketObjectLockConfiguration
|
||||
ErrObjectLockConfigurationNotAllowed
|
||||
ErrObjectLocked
|
||||
ErrPastObjectLockRetainDate
|
||||
ErrNoSuchBucketPolicy
|
||||
@@ -430,6 +431,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "Bucket is missing ObjectLockConfiguration",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrObjectLockConfigurationNotAllowed: {
|
||||
Code: "InvalidBucketState",
|
||||
Description: "Object Lock configuration cannot be enabled on existing buckets",
|
||||
HTTPStatusCode: http.StatusConflict,
|
||||
},
|
||||
ErrObjectLocked: {
|
||||
Code: "InvalidRequest",
|
||||
Description: "Object is WORM protected and cannot be overwritten",
|
||||
|
||||
@@ -310,6 +310,7 @@ func TestDeleteBucketPolicy(s *S3Conf) {
|
||||
func TestPutObjectLockConfiguration(s *S3Conf) {
|
||||
PutObjectLockConfiguration_non_existing_bucket(s)
|
||||
PutObjectLockConfiguration_empty_config(s)
|
||||
PutObjectLockConfiguration_not_enabled_on_bucket_creation(s)
|
||||
PutObjectLockConfiguration_both_years_and_days(s)
|
||||
PutObjectLockConfiguration_success(s)
|
||||
}
|
||||
@@ -628,6 +629,7 @@ func GetIntTests() IntTests {
|
||||
"DeleteBucketPolicy_success": DeleteBucketPolicy_success,
|
||||
"PutObjectLockConfiguration_non_existing_bucket": PutObjectLockConfiguration_non_existing_bucket,
|
||||
"PutObjectLockConfiguration_empty_config": PutObjectLockConfiguration_empty_config,
|
||||
"PutObjectLockConfiguration_not_enabled_on_bucket_creation": PutObjectLockConfiguration_not_enabled_on_bucket_creation,
|
||||
"PutObjectLockConfiguration_both_years_and_days": PutObjectLockConfiguration_both_years_and_days,
|
||||
"PutObjectLockConfiguration_success": PutObjectLockConfiguration_success,
|
||||
"GetObjectLockConfiguration_non_existing_bucket": GetObjectLockConfiguration_non_existing_bucket,
|
||||
|
||||
@@ -6343,6 +6343,30 @@ func PutObjectLockConfiguration_empty_config(s *S3Conf) error {
|
||||
})
|
||||
}
|
||||
|
||||
func PutObjectLockConfiguration_not_enabled_on_bucket_creation(s *S3Conf) error {
|
||||
testName := "PutObjectLockConfiguration_not_enabled_on_bucket_creation"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
var days int32 = 12
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err := s3client.PutObjectLockConfiguration(ctx, &s3.PutObjectLockConfigurationInput{
|
||||
Bucket: &bucket,
|
||||
ObjectLockConfiguration: &types.ObjectLockConfiguration{
|
||||
ObjectLockEnabled: types.ObjectLockEnabledEnabled,
|
||||
Rule: &types.ObjectLockRule{
|
||||
DefaultRetention: &types.DefaultRetention{
|
||||
Days: &days,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
cancel()
|
||||
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrObjectLockConfigurationNotAllowed)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func PutObjectLockConfiguration_both_years_and_days(s *S3Conf) error {
|
||||
testName := "PutObjectLockConfiguration_both_years_and_days"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
@@ -6383,7 +6407,7 @@ func PutObjectLockConfiguration_success(s *S3Conf) error {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func GetObjectLockConfiguration_non_existing_bucket(s *S3Conf) error {
|
||||
@@ -6467,7 +6491,7 @@ func GetObjectLockConfiguration_success(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func PutObjectRetention_non_existing_bucket(s *S3Conf) error {
|
||||
@@ -6510,7 +6534,7 @@ func PutObjectRetention_non_existing_object(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func PutObjectRetention_unset_bucket_object_lock_config(s *S3Conf) error {
|
||||
@@ -6576,7 +6600,7 @@ func PutObjectRetention_disabled_bucket_object_lock_config(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func PutObjectRetention_expired_retain_until_date(s *S3Conf) error {
|
||||
@@ -6603,7 +6627,7 @@ func PutObjectRetention_expired_retain_until_date(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func PutObjectRetention_success(s *S3Conf) error {
|
||||
@@ -6639,7 +6663,7 @@ func PutObjectRetention_success(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func GetObjectRetention_non_existing_bucket(s *S3Conf) error {
|
||||
@@ -6755,7 +6779,7 @@ func GetObjectRetention_success(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func PutObjectLegalHold_non_existing_bucket(s *S3Conf) error {
|
||||
@@ -6796,7 +6820,7 @@ func PutObjectLegalHold_non_existing_object(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func PutObjectLegalHold_invalid_body(s *S3Conf) error {
|
||||
@@ -6875,7 +6899,7 @@ func PutObjectLegalHold_disabled_bucket_object_lock_config(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func PutObjectLegalHold_success(s *S3Conf) error {
|
||||
@@ -6909,7 +6933,7 @@ func PutObjectLegalHold_success(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func GetObjectLegalHold_non_existing_bucket(s *S3Conf) error {
|
||||
@@ -7011,7 +7035,7 @@ func GetObjectLegalHold_success(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func WORMProtection_bucket_object_lock_configuration_compliance_mode(s *S3Conf) error {
|
||||
@@ -7049,7 +7073,7 @@ func WORMProtection_bucket_object_lock_configuration_compliance_mode(s *S3Conf)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func WORMProtection_bucket_object_lock_governance_root_overwrite(s *S3Conf) error {
|
||||
@@ -7090,7 +7114,7 @@ func WORMProtection_bucket_object_lock_governance_root_overwrite(s *S3Conf) erro
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func WORMProtection_object_lock_retention_compliance_root_access_denied(s *S3Conf) error {
|
||||
@@ -7129,7 +7153,7 @@ func WORMProtection_object_lock_retention_compliance_root_access_denied(s *S3Con
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func WORMProtection_object_lock_retention_governance_root_overwrite(s *S3Conf) error {
|
||||
@@ -7169,7 +7193,7 @@ func WORMProtection_object_lock_retention_governance_root_overwrite(s *S3Conf) e
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func WORMProtection_object_lock_retention_governance_user_access_denied(s *S3Conf) error {
|
||||
@@ -7226,7 +7250,7 @@ func WORMProtection_object_lock_retention_governance_user_access_denied(s *S3Con
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func WORMProtection_object_lock_legal_hold_user_access_denied(s *S3Conf) error {
|
||||
@@ -7281,7 +7305,7 @@ func WORMProtection_object_lock_legal_hold_user_access_denied(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
func WORMProtection_object_lock_legal_hold_root_overwrite(s *S3Conf) error {
|
||||
@@ -7319,7 +7343,7 @@ func WORMProtection_object_lock_legal_hold_root_overwrite(s *S3Conf) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}, withLock())
|
||||
}
|
||||
|
||||
// Access control tests (with bucket ACLs and Policies)
|
||||
|
||||
@@ -54,12 +54,18 @@ func getBucketName() string {
|
||||
return fmt.Sprintf("test-bucket-%v", bcktCount)
|
||||
}
|
||||
|
||||
func setup(s *S3Conf, bucket string) error {
|
||||
func setup(s *S3Conf, bucket string, opts ...setupOpt) error {
|
||||
s3client := s3.NewFromConfig(s.Config())
|
||||
|
||||
cfg := new(setupCfg)
|
||||
for _, opt := range opts {
|
||||
opt(cfg)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err := s3client.CreateBucket(ctx, &s3.CreateBucketInput{
|
||||
Bucket: &bucket,
|
||||
Bucket: &bucket,
|
||||
ObjectLockEnabledForBucket: &cfg.LockEnabled,
|
||||
})
|
||||
cancel()
|
||||
return err
|
||||
@@ -113,10 +119,20 @@ func teardown(s *S3Conf, bucket string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func actionHandler(s *S3Conf, testName string, handler func(s3client *s3.Client, bucket string) error) error {
|
||||
type setupCfg struct {
|
||||
LockEnabled bool
|
||||
}
|
||||
|
||||
type setupOpt func(*setupCfg)
|
||||
|
||||
func withLock() setupOpt {
|
||||
return func(s *setupCfg) { s.LockEnabled = true }
|
||||
}
|
||||
|
||||
func actionHandler(s *S3Conf, testName string, handler func(s3client *s3.Client, bucket string) error, opts ...setupOpt) error {
|
||||
runF(testName)
|
||||
bucketName := getBucketName()
|
||||
err := setup(s, bucketName)
|
||||
err := setup(s, bucketName, opts...)
|
||||
if err != nil {
|
||||
failF("%v: failed to create a bucket: %v", testName, err)
|
||||
return fmt.Errorf("%v: failed to create a bucket: %w", testName, err)
|
||||
|
||||
Reference in New Issue
Block a user