]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: implement ConfirmRemoveSelfBucketAccess header for bucket policy
authorSeena Fallah <seenafallah@gmail.com>
Wed, 22 May 2024 12:34:59 +0000 (14:34 +0200)
committerSeena Fallah <seenafallah@gmail.com>
Tue, 18 Feb 2025 13:51:41 +0000 (14:51 +0100)
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 <seenafallah@gmail.com>
PendingReleaseNotes
src/rgw/rgw_common.h
src/rgw/rgw_op.cc

index 5b0412bf0182e5d790f0c9d5b76df565fb109684..31528a224e102d110243ddeb63fdb61ce4ba7cdc 100644 (file)
   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
index 88f5f7a9c52a0bbc738ab7799d90060e5091a51e..787ca6e8684c871f7af0de986e95bc9f73f72c23 100644 (file)
@@ -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"
index 0095395237c9627d818f1e2c8e3ec8bbde3c3da4..1042b8da43c7e07e61748e931c8982112efe38f3 100644 (file)
@@ -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);