From b454668983fe45687f9f77c75628a4d641dd545b Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Thu, 20 Feb 2025 14:42:37 -0500 Subject: [PATCH] rgw: PutObjectLockConfiguration can enable object lock on existing buckets AWS now allows PutObjectLockConfiguration on existing buckets, even if x-amz-bucket-object-lock-enabled was not specified on bucket creation object lock still requires the bucket to be versioning-enabled, so such requests are rejected otherwise. if the bucket is versioning-enabled but not object-lock-enabled, enable the BUCKET_OBJ_LOCK_ENABLED flag this logic was moved into retry_raced_bucket_write() in case the request races with PutBucketVersioning Fixes: https://tracker.ceph.com/issues/70013 Signed-off-by: Casey Bodley --- PendingReleaseNotes | 3 +++ src/rgw/rgw_op.cc | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/PendingReleaseNotes b/PendingReleaseNotes index 24a8182eb284c..85498ee2dc418 100644 --- a/PendingReleaseNotes +++ b/PendingReleaseNotes @@ -72,6 +72,9 @@ headers only when the `read-stats` querystring is explicitly included in the API request. +* RGW: PutObjectLockConfiguration can now be used to enable S3 Object Lock on an + existing versioning-enabled bucket that was not created with Object Lock enabled. + * RADOS: The ceph df command reports incorrect MAX AVAIL for stretch mode pools when CRUSH rules use multiple take steps for datacenters. PGMap::get_rule_avail incorrectly calculates available space from only one datacenter. diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 0095395237c96..69d0d62f012c8 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -8651,8 +8651,9 @@ int RGWPutBucketObjectLock::verify_permission(optional_yield y) void RGWPutBucketObjectLock::execute(optional_yield y) { - if (!s->bucket->get_info().obj_lock_enabled()) { - s->err.message = "object lock configuration can't be set if bucket object lock not enabled"; + if (!s->bucket->get_info().versioning_enabled()) { + s->err.message = "Object lock cannot be enabled unless the " + "bucket has versioning enabled"; ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl; op_ret = -ERR_INVALID_BUCKET_STATE; return; @@ -8695,6 +8696,17 @@ void RGWPutBucketObjectLock::execute(optional_yield y) } op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this, y] { + if (!s->bucket->get_info().obj_lock_enabled()) { + // automatically enable object lock if the bucket is versioning-enabled + if (!s->bucket->get_info().versioning_enabled()) { + s->err.message = "Object lock cannot be enabled unless the " + "bucket has versioning enabled"; + ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl; + return -ERR_INVALID_BUCKET_STATE; + } + s->bucket->get_info().flags |= BUCKET_OBJ_LOCK_ENABLED; + } + s->bucket->get_info().obj_lock = obj_lock; op_ret = s->bucket->put_info(this, false, real_time(), y); return op_ret; -- 2.39.5