From d3009d41bf93a30740db5ca67272b3e303512026 Mon Sep 17 00:00:00 2001 From: Matt Benjamin Date: Sun, 9 Mar 2025 12:30:24 -0400 Subject: [PATCH] rgw: introduce rgw_bucket_eexist_override S3: conditionally override 200, OK result for same-owner CreateBucket requests * also send an error message to avoid confusing awscli * maps ERR_BUCKET_EXISTS to the same result, message as EEXIST Fixes: https://tracker.ceph.com/issues/70369 Signed-off-by: Matt Benjamin --- doc/radosgw/s3/bucketops.rst | 4 +++- src/common/options/rgw.yaml.in | 9 +++++++++ src/rgw/rgw_common.cc | 1 + src/rgw/rgw_op.cc | 4 ++-- src/rgw/rgw_rest_s3.cc | 14 +++++++++++--- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/doc/radosgw/s3/bucketops.rst b/doc/radosgw/s3/bucketops.rst index c33a8c0f4100b..8153d7e57e5fb 100644 --- a/doc/radosgw/s3/bucketops.rst +++ b/doc/radosgw/s3/bucketops.rst @@ -59,7 +59,9 @@ HTTP Response ~~~~~~~~~~~~~ If the bucket name is unique, within constraints and unused, the operation will succeed. -If a bucket with the same name already exists and the user is the bucket owner, the operation will succeed. +If a bucket with the same name already exists and the user is the +bucket owner, the operation will succeed unless non-default option +``rgw_bucket_eexist_override`` is `true`. If the bucket name is already in use, the operation will fail. +---------------+-----------------------+----------------------------------------------------------+ diff --git a/src/common/options/rgw.yaml.in b/src/common/options/rgw.yaml.in index 5b9730f8761b5..52bd7b2145a31 100644 --- a/src/common/options/rgw.yaml.in +++ b/src/common/options/rgw.yaml.in @@ -4349,3 +4349,12 @@ options: flags: - startup with_legacy: true +- name: rgw_bucket_eexist_override + type: bool + level: advanced + desc: CreateBucket on an existing bucket of the same owner returns 409/EEXIST, regardless of region. + long_desc: Overrides the documented RGW behavior that treats multiple CreateBucket operations by the same + owner as idempotent + default: false + services: + - rgw diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index c11521f8cbf71..25d85cabb8336 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -112,6 +112,7 @@ rgw_http_errors rgw_http_s3_errors({ { ERR_METHOD_NOT_ALLOWED, {405, "MethodNotAllowed" }}, { ETIMEDOUT, {408, "RequestTimeout" }}, { EEXIST, {409, "BucketAlreadyExists" }}, + { ERR_BUCKET_EXISTS, {409, "BucketAlreadyExists" }}, { ERR_USER_EXIST, {409, "UserAlreadyExists" }}, { ERR_EMAIL_EXIST, {409, "EmailExists" }}, { ERR_KEY_EXIST, {409, "KeyExists"}}, diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 81c32f5449b86..1ef57eda49595 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -3889,8 +3889,8 @@ void RGWCreateBucket::execute(optional_yield y) if (op_ret >= 0) { op_ret = -ERR_BUCKET_EXISTS; } - } -} + } /* if (need_metadata_upload() && existed) */ +} /* RGWCreateBucket::execute() */ int RGWDeleteBucket::verify_permission(optional_yield y) { diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 76331cc607bc8..b21ca83afd9ec 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -2692,10 +2692,18 @@ int RGWCreateBucket_ObjStore_S3::get_params(optional_yield y) void RGWCreateBucket_ObjStore_S3::send_response() { - if (op_ret == -ERR_BUCKET_EXISTS) - op_ret = 0; - if (op_ret) + if (op_ret == -ERR_BUCKET_EXISTS) { + const auto eexist_override = s->cct->_conf.get_val("rgw_bucket_eexist_override"); + if (! eexist_override) [[likely]] { + op_ret = 0; + } else { + s->err.message = "The requested bucket name is not available. The bucket namespace is shared by all users of the system. Specify a different name and try again."; + } + } + + if (op_ret) { set_req_state_err(s, op_ret); + } dump_errno(s); end_header(s); -- 2.39.5