From 1b45be0d60cd90d418c3d346db7e295b6bc15d44 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Thu, 9 Apr 2020 17:28:57 +0100 Subject: [PATCH] lifecycle: Disallow delete when the object is locked (#9272) --- cmd/daily-lifecycle-ops.go | 11 ++++++++++- cmd/object-lock.go | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/cmd/daily-lifecycle-ops.go b/cmd/daily-lifecycle-ops.go index 165d3167a..eb9cd4548 100644 --- a/cmd/daily-lifecycle-ops.go +++ b/cmd/daily-lifecycle-ops.go @@ -51,6 +51,11 @@ func startDailyLifecycle(ctx context.Context, objAPI ObjectLayer) { } func lifecycleRound(ctx context.Context, objAPI ObjectLayer) error { + // No action is expected when WORM is enabled + if globalWORMEnabled { + return nil + } + buckets, err := objAPI.ListBuckets(ctx) if err != nil { return err @@ -63,6 +68,8 @@ func lifecycleRound(ctx context.Context, objAPI ObjectLayer) error { continue } + _, bucketHasLockConfig := globalBucketObjectLockConfig.Get(bucket.Name) + // Calculate the common prefix of all lifecycle rules var prefixes []string for _, rule := range l.Rules { @@ -85,9 +92,11 @@ func lifecycleRound(ctx context.Context, objAPI ObjectLayer) error { // Reached maximum delete requests, attempt a delete for now. break } - // Find the action that need to be executed if l.ComputeAction(obj.Name, obj.UserTags, obj.ModTime) == lifecycle.DeleteAction { + if bucketHasLockConfig && enforceRetentionForLifecycle(ctx, obj) { + continue + } objects = append(objects, obj.Name) } } diff --git a/cmd/object-lock.go b/cmd/object-lock.go index 528972ac6..d3fd2bbb9 100644 --- a/cmd/object-lock.go +++ b/cmd/object-lock.go @@ -98,6 +98,28 @@ func enforceRetentionBypassForDeleteWeb(ctx context.Context, r *http.Request, bu return ErrNone } +// enforceRetentionForLifecycle checks if it is appropriate to remove an +// object according to locking configuration when this is lifecycle asking. +func enforceRetentionForLifecycle(ctx context.Context, objInfo ObjectInfo) (locked bool) { + lhold := objectlock.GetObjectLegalHoldMeta(objInfo.UserDefined) + if lhold.Status.Valid() && lhold.Status == objectlock.LegalHoldOn { + return true + } + + ret := objectlock.GetObjectRetentionMeta(objInfo.UserDefined) + if ret.Mode.Valid() && (ret.Mode == objectlock.RetCompliance || ret.Mode == objectlock.RetGovernance) { + t, err := objectlock.UTCNowNTP() + if err != nil { + logger.LogIf(ctx, err) + return true + } + if ret.RetainUntilDate.After(t) { + return true + } + } + return false +} + // enforceRetentionBypassForDelete enforces whether an existing object under governance can be deleted // with governance bypass headers set in the request. // Objects under site wide WORM can never be overwritten.