Disallow ExpiredObjectAllVersions with object lock (#19792)

Relaxes restrictions on Expiration and NoncurrentVersionExpiration
placed by https://github.com/minio/minio/pull/19785.
ref: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock-managing.html#object-lock-managing-lifecycle

> Object lifecycle management configurations continue functioning
normally on protected objects, including placing delete markers.
However, a locked version of an object cannot be deleted by a S3
Lifecycle expiration policy. Object Lock is maintained regardless of
the object's storage class and throughout S3 Lifecycle
transitions between storage classes.
This commit is contained in:
Krishnan Parthasarathi 2024-05-22 18:12:48 -07:00 committed by GitHub
parent d38e020b29
commit 6d5bc045bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 16 deletions

View File

@ -36,7 +36,7 @@ var (
errLifecycleNoRule = Errorf("Lifecycle configuration should have at least one rule") errLifecycleNoRule = Errorf("Lifecycle configuration should have at least one rule")
errLifecycleDuplicateID = Errorf("Rule ID must be unique. Found same ID for more than one rule") errLifecycleDuplicateID = Errorf("Rule ID must be unique. Found same ID for more than one rule")
errXMLNotWellFormed = Errorf("The XML you provided was not well-formed or did not validate against our published schema") errXMLNotWellFormed = Errorf("The XML you provided was not well-formed or did not validate against our published schema")
errLifecycleBucketLocked = Errorf("--expire-day, --expire-delete-marker, --expire-all-object-versions and --noncurrent-expire-days can't be used for locked bucket") errLifecycleBucketLocked = Errorf("ExpiredObjectAllVersions element and DelMarkerExpiration action cannot be used on an object locked bucket")
) )
const ( const (
@ -253,10 +253,7 @@ func (lc Lifecycle) Validate(lr lock.Retention) error {
if err := r.Validate(); err != nil { if err := r.Validate(); err != nil {
return err return err
} }
if (r.Expiration.DeleteMarker.val || // DeleteVersionAction if lr.LockEnabled && (r.Expiration.DeleteAll.val || !r.DelMarkerExpiration.Empty()) {
!r.DelMarkerExpiration.Empty() || // DelMarkerDeleteAllVersionsAction
!r.NoncurrentVersionExpiration.IsDaysNull() || // DeleteVersionAction
!r.Expiration.IsDaysNull()) && lr.LockEnabled {
return errLifecycleBucketLocked return errLifecycleBucketLocked
} }
} }

View File

@ -63,25 +63,39 @@ func TestParseAndValidateLifecycleConfig(t *testing.T) {
expectedParsingErr: nil, expectedParsingErr: nil,
expectedValidationErr: nil, expectedValidationErr: nil,
}, },
{ // invalid lifecycle config { // Using ExpiredObjectAllVersions element with an object locked bucket
inputConfig: `<LifecycleConfiguration> inputConfig: `<LifecycleConfiguration>
<Rule> <Rule>
<ID>testRule1</ID> <ID>ExpiredObjectAllVersions with object locking</ID>
<Filter> <Filter>
<Prefix>prefix</Prefix> <Prefix>prefix</Prefix>
</Filter> </Filter>
<Status>Enabled</Status> <Status>Enabled</Status>
<Expiration><Days>3</Days></Expiration> <Expiration>
</Rule> <Days>3</Days>
<Rule> <ExpiredObjectAllVersions>true</ExpiredObjectAllVersions>
<ID>testRule2</ID> </Expiration>
</Rule>
</LifecycleConfiguration>`,
expectedParsingErr: nil,
expectedValidationErr: errLifecycleBucketLocked,
lr: lock.Retention{
LockEnabled: true,
},
},
{ // Using DelMarkerExpiration action with an object locked bucket
inputConfig: `<LifecycleConfiguration>
<Rule>
<ID>DeleteMarkerExpiration with object locking</ID>
<Filter> <Filter>
<Prefix>another-prefix</Prefix> <Prefix>prefix</Prefix>
</Filter> </Filter>
<Status>Enabled</Status> <Status>Enabled</Status>
<Expiration><Days>3</Days></Expiration> <DelMarkerExpiration>
</Rule> <Days>3</Days>
</LifecycleConfiguration>`, </DelMarkerExpiration>
</Rule>
</LifecycleConfiguration>`,
expectedParsingErr: nil, expectedParsingErr: nil,
expectedValidationErr: errLifecycleBucketLocked, expectedValidationErr: errLifecycleBucketLocked,
lr: lock.Retention{ lr: lock.Retention{