From: Seena Fallah Date: Wed, 22 May 2024 12:34:59 +0000 (+0200) Subject: rgw: implement ConfirmRemoveSelfBucketAccess header for bucket policy X-Git-Tag: v20.3.0~324^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=753fcff94d121bad948808538a0649984a6d3a24;p=ceph.git rgw: implement ConfirmRemoveSelfBucketAccess header for bucket policy According to https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html root user should always have access to do Put/Get/DeleteBucketPolicy. By implementing the `x-amz-confirm-remove-self-bucket-access` header this privilege can also be dropped from the root user. Fixes: https://tracker.ceph.com/issues/66177 Signed-off-by: Seena Fallah --- diff --git a/PendingReleaseNotes b/PendingReleaseNotes index 5b0412bf018..31528a224e1 100644 --- a/PendingReleaseNotes +++ b/PendingReleaseNotes @@ -82,6 +82,10 @@ redistribution. In contrast, a stretch rule with a single-take configuration will not cause any data movement during the upgrade process. +* RGW: The `x-amz-confirm-remove-self-bucket-access` header is now supported by + `PutBucketPolicy`. Additionally, the root user will always have access to modify + the bucket policy, even if the current policy explicitly denies access. + >=19.2.1 * CephFS: Command `fs subvolume create` now allows tagging subvolumes through option diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 88f5f7a9c52..787ca6e8684 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -163,10 +163,11 @@ using ceph::crypto::MD5; #define RGW_ATTR_OBJ_REPLICATION_TIMESTAMP RGW_ATTR_PREFIX "replicated-at" /* IAM Policy */ -#define RGW_ATTR_IAM_POLICY RGW_ATTR_PREFIX "iam-policy" -#define RGW_ATTR_USER_POLICY RGW_ATTR_PREFIX "user-policy" -#define RGW_ATTR_MANAGED_POLICY RGW_ATTR_PREFIX "managed-policy" -#define RGW_ATTR_PUBLIC_ACCESS RGW_ATTR_PREFIX "public-access" +#define RGW_ATTR_IAM_POLICY RGW_ATTR_PREFIX "iam-policy" +#define RGW_ATTR_USER_POLICY RGW_ATTR_PREFIX "user-policy" +#define RGW_ATTR_MANAGED_POLICY RGW_ATTR_PREFIX "managed-policy" +#define RGW_ATTR_PUBLIC_ACCESS RGW_ATTR_PREFIX "public-access" +#define RGW_ATTR_IAM_POLICY_REMOVE_SELF_ACCESS RGW_ATTR_PREFIX "iam-policy-remove-self-access" /* RGW File Attributes */ #define RGW_ATTR_UNIX_KEY1 RGW_ATTR_PREFIX "unix-key1" diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 0095395237c..1042b8da43c 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -8481,6 +8481,14 @@ void RGWPutBucketPolicy::send_response() int RGWPutBucketPolicy::verify_permission(optional_yield y) { + // If the user is the root account of the bucket owner, + // and x-amz-confirm-remove-self-bucket-access was not set, + // then the user can put bucket policy. + if (s->auth.identity->is_root_of(s->bucket_owner.id) && + s->bucket_attrs.find(RGW_ATTR_IAM_POLICY_REMOVE_SELF_ACCESS) == s->bucket_attrs.end()) { + return 0; + } + auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, s, false); if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); @@ -8530,10 +8538,15 @@ void RGWPutBucketPolicy::execute(optional_yield y) } op_ret = retry_raced_bucket_write(this, s->bucket.get(), [&p, this, &attrs] { - attrs[RGW_ATTR_IAM_POLICY].clear(); - attrs[RGW_ATTR_IAM_POLICY].append(p.text); - op_ret = s->bucket->merge_and_store_attrs(this, attrs, s->yield); - return op_ret; + attrs[RGW_ATTR_IAM_POLICY].clear(); + attrs[RGW_ATTR_IAM_POLICY].append(p.text); + if (s->info.env->exists("HTTP_X_AMZ_CONFIRM_REMOVE_SELF_BUCKET_ACCESS")) { + attrs[RGW_ATTR_IAM_POLICY_REMOVE_SELF_ACCESS].clear(); + } else { + attrs.erase(RGW_ATTR_IAM_POLICY_REMOVE_SELF_ACCESS); + } + op_ret = s->bucket->merge_and_store_attrs(this, attrs, s->yield); + return op_ret; }, y); } catch (rgw::IAM::PolicyParseException& e) { ldpp_dout(this, 5) << "failed to parse policy: " << e.what() << dendl; @@ -8554,6 +8567,14 @@ void RGWGetBucketPolicy::send_response() int RGWGetBucketPolicy::verify_permission(optional_yield y) { + // If the user is the root account of the bucket owner, + // and x-amz-confirm-remove-self-bucket-access was not set, + // then the user can put bucket policy. + if (s->auth.identity->is_root_of(s->bucket_owner.id) && + s->bucket_attrs.find(RGW_ATTR_IAM_POLICY_REMOVE_SELF_ACCESS) == s->bucket_attrs.end()) { + return 0; + } + auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, s, false); if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); @@ -8603,6 +8624,14 @@ void RGWDeleteBucketPolicy::send_response() int RGWDeleteBucketPolicy::verify_permission(optional_yield y) { + // If the user is the root account of the bucket owner, + // and x-amz-confirm-remove-self-bucket-access was not set, + // then the user can put bucket policy. + if (s->auth.identity->is_root_of(s->bucket_owner.id) && + s->bucket_attrs.find(RGW_ATTR_IAM_POLICY_REMOVE_SELF_ACCESS) == s->bucket_attrs.end()) { + return 0; + } + auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, s, false); if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); @@ -8626,6 +8655,7 @@ void RGWDeleteBucketPolicy::execute(optional_yield y) op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] { rgw::sal::Attrs& attrs = s->bucket->get_attrs(); attrs.erase(RGW_ATTR_IAM_POLICY); + attrs.erase(RGW_ATTR_IAM_POLICY_REMOVE_SELF_ACCESS); op_ret = s->bucket->put_info(this, false, real_time(), s->yield); return op_ret; }, y);