]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/auth: object ops use new verify_bucket_permission() overload
authorCasey Bodley <cbodley@redhat.com>
Fri, 1 Mar 2024 14:36:31 +0000 (09:36 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 12 Apr 2024 19:34:29 +0000 (15:34 -0400)
several object operations like PutObject, DeleteObject, etc were handling
policy evaluation manually instead of using the helper functions like
verify_user/bucket/object_permission(), so were missing the cross-policy
evaluation rules for account users

these now call the new 'custom arn' overload of verify_bucket_permission()
for equivalent functionality

the eval_identity_or_session_policies() function is no longer exposed by
rgw_common.h to prevent other ops from adding new logic that doesn't
handle cross-account access

Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit 315ded47868de276de644315767d9ea2fab9c845)

src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_rest_swift.h

index 6f676a42aaa5377d3d9d0a2d86b8393ad68f7f09..7c878eea25442f7fd7b5e57a7c8f4d82ab6e0212 100644 (file)
@@ -1129,8 +1129,6 @@ Effect eval_or_pass(const DoutPrefixProvider* dpp,
     return policy->eval(env, id, op, resource, princ_type);
 }
 
-}
-
 Effect eval_identity_or_session_policies(const DoutPrefixProvider* dpp,
                          const vector<Policy>& policies,
                           const rgw::IAM::Environment& env,
@@ -1229,6 +1227,8 @@ Effect evaluate_iam_policies(
   return Effect::Pass;
 }
 
+} // anonymous namespace
+
 bool verify_user_permission(const DoutPrefixProvider* dpp,
                             perm_state_base * const s,
                             const RGWAccessControlPolicy& user_acl,
index 12f07e29506aba8a7e3217f0ad360b9d83edbe02..6b3e350bae02e8c1f30c0b617a53e67fd31764a7 100644 (file)
@@ -1761,13 +1761,6 @@ bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp,
                                        const RGWAccessControlPolicy& object_acl,
                                        const int perm);
 
-/** Check if the req_state's user has the necessary permissions
- * to do the requested action */
-rgw::IAM::Effect eval_identity_or_session_policies(const DoutPrefixProvider* dpp,
-                         const std::vector<rgw::IAM::Policy>& user_policies,
-                          const rgw::IAM::Environment& env,
-                          const uint64_t op,
-                          const rgw::ARN& arn);
 bool verify_user_permission(const DoutPrefixProvider* dpp,
                             req_state * const s,
                             const RGWAccessControlPolicy& user_acl,
index f30077ea484760e5639ae83c38b34adfda2594ea..481e14b541647d8a3efeba82312380c1b31bfa9e 100644 (file)
@@ -422,45 +422,26 @@ static int read_obj_policy(const DoutPrefixProvider *dpp,
   int ret = get_obj_policy_from_attr(dpp, s->cct, driver, s->bucket_owner,
                                     acl, storage_class, object, s->yield);
   if (ret == -ENOENT) {
-    /* object does not exist checking the bucket's ACL to make sure
-       that we send a proper error code */
+    // the object doesn't exist, but we can't expose that information to clients
+    // that don't have permission to list the bucket and learn that for
+    // themselves. in that case, return -EACCES instead
     RGWAccessControlPolicy bucket_policy;
     ret = rgw_op_get_bucket_policy_from_attr(dpp, s->cct, driver, bucket_info.owner,
                                              bucket_attrs, bucket_policy, y);
     if (ret < 0) {
       return ret;
     }
-    const rgw_owner& bucket_owner = bucket_policy.get_owner().id;
-    if (bucket_owner != s->owner.id &&
-        !s->auth.identity->is_admin_of(bucket_owner)) {
-      auto r = eval_identity_or_session_policies(dpp, s->iam_identity_policies, s->env,
-                                  rgw::IAM::s3ListBucket, ARN(bucket->get_key()));
-      if (r == Effect::Allow)
-        return -ENOENT;
-      if (r == Effect::Deny)
-        return -EACCES;
-      if (policy) {
-        ARN b_arn(bucket->get_key());
-        r = policy->eval(s->env, *s->auth.identity, rgw::IAM::s3ListBucket, b_arn);
-        if (r == Effect::Allow)
-          return -ENOENT;
-        if (r == Effect::Deny)
-          return -EACCES;
-      }
-      if (! s->session_policies.empty()) {
-        r = eval_identity_or_session_policies(dpp, s->session_policies, s->env,
-                                  rgw::IAM::s3ListBucket, ARN(bucket->get_key()));
-        if (r == Effect::Allow)
-          return -ENOENT;
-        if (r == Effect::Deny)
-          return -EACCES;
-      }
-      if (! bucket_policy.verify_permission(s, *s->auth.identity, s->perm_mask, RGW_PERM_READ))
-        ret = -EACCES;
-      else
-        ret = -ENOENT;
+
+    if (s->auth.identity->is_admin_of(bucket_policy.get_owner().id)) {
+      return -ENOENT;
+    }
+
+    if (verify_bucket_permission(dpp, s, bucket->get_key(), s->user_acl,
+                                 bucket_policy, policy, s->iam_identity_policies,
+                                 s->session_policies, rgw::IAM::s3ListBucket)) {
+      return -ENOENT;
     } else {
-      ret = -ENOENT;
+      return -EACCES;
     }
   }
 
@@ -3898,8 +3879,22 @@ int RGWPutObj::init_processing(optional_yield y) {
         return ret;
       }
     }
-
   } /* copy_source */
+
+  // reject public canned acls
+  if (s->bucket_access_conf && s->bucket_access_conf->block_public_acls() &&
+      (s->canned_acl.compare("public-read") ||
+       s->canned_acl.compare("public-read-write") ||
+       s->canned_acl.compare("authenticated-read"))) {
+    return -EACCES;
+  }
+
+  ret = get_params(y);
+  if (ret < 0) {
+    ldpp_dout(this, 20) << "get_params() returned ret=" << ret << dendl;
+    return ret;
+  }
+
   return RGWOp::init_processing(y);
 }
 
@@ -3923,129 +3918,54 @@ int RGWPutObj::verify_permission(optional_yield y)
       return ret;
     }
 
-    /* admin request overrides permission checks */
-    if (! s->auth.identity->is_admin_of(cs_acl.get_owner().id)) {
-      if (policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-        //add source object tags for permission evaluation
-        auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, policy, s->iam_identity_policies, s->session_policies);
-        if (has_s3_existing_tag || has_s3_resource_tag)
-          rgw_iam_add_objtags(this, s, cs_object.get(), has_s3_existing_tag, has_s3_resource_tag);
-        auto usr_policy_res = Effect::Pass;
-        rgw::ARN obj_arn(cs_object->get_obj());
-        for (auto& user_policy : s->iam_identity_policies) {
-          if (usr_policy_res = user_policy.eval(s->env, boost::none,
-                             cs_object->get_instance().empty() ?
-                             rgw::IAM::s3GetObject :
-                             rgw::IAM::s3GetObjectVersion,
-                             obj_arn); usr_policy_res == Effect::Deny)
-            return -EACCES;
-          else if (usr_policy_res == Effect::Allow)
-            break;
-        }
-  rgw::IAM::Effect e = Effect::Pass;
-  if (policy) {
-    rgw::ARN obj_arn(cs_object->get_obj());
-         e = policy->eval(s->env, *s->auth.identity,
-                             cs_object->get_instance().empty() ?
-                             rgw::IAM::s3GetObject :
-                             rgw::IAM::s3GetObjectVersion,
-                             obj_arn);
-  }
-       if (e == Effect::Deny) {
-         return -EACCES; 
-       } else if (usr_policy_res == Effect::Pass && e == Effect::Pass &&
-                  !cs_acl.verify_permission(this, *s->auth.identity, s->perm_mask,
-                                               RGW_PERM_READ)) {
-         return -EACCES;
-       }
-      rgw_iam_remove_objtags(this, s, cs_object.get(), has_s3_existing_tag, has_s3_resource_tag);
-      } else if (!cs_acl.verify_permission(this, *s->auth.identity, s->perm_mask,
-                                          RGW_PERM_READ)) {
-       return -EACCES;
-      }
+    RGWAccessControlPolicy cs_bucket_acl;
+    ret = rgw_op_get_bucket_policy_from_attr(this, s->cct, driver,
+                                             copy_source_bucket_info.owner,
+                                             cs_attrs, cs_bucket_acl, y);
+    if (ret < 0) {
+      return ret;
     }
-  }
-
-  if (s->bucket_access_conf && s->bucket_access_conf->block_public_acls()) {
-    if (s->canned_acl.compare("public-read") ||
-        s->canned_acl.compare("public-read-write") ||
-        s->canned_acl.compare("authenticated-read"))
-      return -EACCES;
-  }
-
-  int ret = get_params(y);
-  if (ret < 0) {
-    ldpp_dout(this, 20) << "get_params() returned ret=" << ret << dendl;
-    return ret;
-  }
 
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-    rgw_add_grant_to_iam_environment(s->env, s);
+    // add source object tags for permission evaluation
+    auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, policy, s->iam_identity_policies, s->session_policies);
+    if (has_s3_existing_tag || has_s3_resource_tag)
+      rgw_iam_add_objtags(this, s, cs_object.get(), has_s3_existing_tag, has_s3_resource_tag);
 
-    rgw_add_to_iam_environment(s->env, "s3:x-amz-acl", s->canned_acl);
+    const auto action = cs_object->get_instance().empty() ?
+        rgw::IAM::s3GetObject :
+        rgw::IAM::s3GetObjectVersion;
 
-    if (obj_tags != nullptr && obj_tags->count() > 0){
-      auto tags = obj_tags->get_tags();
-      for (const auto& kv: tags){
-        rgw_add_to_iam_environment(s->env, "s3:RequestObjectTag/"+kv.first, kv.second);
-      }
+    if (!verify_object_permission(this, s, cs_object->get_obj(),
+                                  s->user_acl, cs_bucket_acl, cs_acl,
+                                  policy, s->iam_identity_policies,
+                                  s->session_policies, action)) {
+      return -EACCES;
     }
 
-    // add server-side encryption headers
-    rgw_iam_add_crypt_attrs(s->env, s->info.crypt_attribute_map);
-
-    // Add bucket tags for authorization
-    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);
+    rgw_iam_remove_objtags(this, s, cs_object.get(), has_s3_existing_tag, has_s3_resource_tag);
+  }
 
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                            rgw::IAM::s3PutObject,
-                                            s->object->get_obj());
-    if (identity_policy_res == Effect::Deny)
-      return -EACCES;
+  rgw_add_grant_to_iam_environment(s->env, s);
 
-    rgw::IAM::Effect e = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    if (s->iam_policy) {
-      ARN obj_arn(s->object->get_obj());
-      e = s->iam_policy->eval(s->env, *s->auth.identity,
-          rgw::IAM::s3PutObject,
-          obj_arn,
-          princ_type);
-    }
-    if (e == Effect::Deny) {
-      return -EACCES;
-    }
+  rgw_add_to_iam_environment(s->env, "s3:x-amz-acl", s->canned_acl);
 
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              rgw::IAM::s3PutObject,
-                                              s->object->get_obj());
-      if (session_policy_res == Effect::Deny) {
-          return -EACCES;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && e == Effect::Allow))
-          return 0;
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow)
-          return 0;
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow)
-          return 0;
-      }
-      return -EACCES;
-    }
-    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
-      return 0;
+  if (obj_tags != nullptr && obj_tags->count() > 0){
+    auto tags = obj_tags->get_tags();
+    for (const auto& kv: tags){
+      rgw_add_to_iam_environment(s->env, "s3:RequestObjectTag/"+kv.first, kv.second);
     }
   }
 
-  if (!verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
+  // add server-side encryption headers
+  rgw_iam_add_crypt_attrs(s->env, s->info.crypt_attribute_map);
+
+  // Add bucket tags for authorization
+  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);
+
+  if (!verify_bucket_permission(this, s, ARN(s->object->get_obj()),
+                                rgw::IAM::s3PutObject)) {
     return -EACCES;
   }
 
@@ -4624,8 +4544,34 @@ void RGWPutObj::execute(optional_yield y)
   }
 }
 
+int RGWPostObj::init_processing(optional_yield y)
+{
+  /* Read in the data from the POST form. */
+  int ret = get_params(y);
+  if (ret < 0) {
+    return ret;
+  }
+
+  ret = verify_params();
+  if (ret < 0) {
+    return ret;
+  }
+
+  return RGWOp::init_processing(y);
+}
+
 int RGWPostObj::verify_permission(optional_yield y)
 {
+  // add server-side encryption headers
+  rgw_iam_add_crypt_attrs(s->env, s->info.crypt_attribute_map);
+
+  ldpp_dout(this, 20) << "user policy count=" << s->iam_identity_policies.size() << dendl;
+
+  if (!verify_bucket_permission(this, s, ARN(s->object->get_obj()),
+                                rgw::IAM::s3PutObject)) {
+    return -EACCES;
+  }
+
   return 0;
 }
 
@@ -4640,82 +4586,6 @@ void RGWPostObj::execute(optional_yield y)
   CompressorRef plugin;
   char supplied_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
 
-  /* Read in the data from the POST form. */
-  op_ret = get_params(y);
-  if (op_ret < 0) {
-    return;
-  }
-
-  op_ret = verify_params();
-  if (op_ret < 0) {
-    return;
-  }
-
-  // add server-side encryption headers
-  rgw_iam_add_crypt_attrs(s->env, s->info.crypt_attribute_map);
-
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                            rgw::IAM::s3PutObject,
-                                            s->object->get_obj());
-    if (identity_policy_res == Effect::Deny) {
-      op_ret = -EACCES;
-      return;
-    }
-
-    rgw::IAM::Effect e = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    if (s->iam_policy) {
-      ARN obj_arn(s->object->get_obj());
-      e = s->iam_policy->eval(s->env, *s->auth.identity,
-                                rgw::IAM::s3PutObject,
-                                obj_arn,
-         princ_type);
-    }
-    if (e == Effect::Deny) {
-      op_ret = -EACCES;
-      return;
-    }
-
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              rgw::IAM::s3PutObject,
-                                              s->object->get_obj());
-      if (session_policy_res == Effect::Deny) {
-          op_ret = -EACCES;
-          return;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
-          op_ret = 0;
-          return;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
-          op_ret = 0;
-          return;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
-          op_ret = 0;
-          return;
-        }
-      }
-      op_ret = -EACCES;
-      return;
-    }
-    if (identity_policy_res == Effect::Pass && e == Effect::Pass && !verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
-      op_ret = -EACCES;
-      return;
-    }
-  } else if (!verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
-    op_ret = -EACCES;
-    return;
-  }
-
   // make reservation for notification if needed
   std::unique_ptr<rgw::sal::Notification> res
     = driver->get_notification(s->object.get(), s->src_object.get(), s, rgw::notify::ObjectCreatedPost, y);
@@ -5224,93 +5094,33 @@ int RGWDeleteObj::handle_slo_manifest(bufferlist& bl, optional_yield y)
   return 0;
 }
 
-int RGWDeleteObj::verify_permission(optional_yield y)
+int RGWDeleteObj::init_processing(optional_yield y)
 {
-  int op_ret = get_params(y);
-  if (op_ret) {
-    return op_ret;
+  int ret = get_params(y);
+  if (ret) {
+    return ret;
   }
+  return RGWOp::init_processing(y);
+}
 
+int RGWDeleteObj::verify_permission(optional_yield y)
+{
   auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, s);
-    if (has_s3_existing_tag || has_s3_resource_tag)
-      rgw_iam_add_objtags(this, s, has_s3_existing_tag, has_s3_resource_tag);
-
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || ! s->session_policies.empty()) {
-    if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) {
-      auto r = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                               rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key(), s->object->get_name()));
-      if (r == Effect::Deny) {
-        bypass_perm = false;
-      } else if (r == Effect::Pass && s->iam_policy) {
-        ARN obj_arn(ARN(s->bucket->get_key(), s->object->get_name()));
-        r = s->iam_policy->eval(s->env, *s->auth.identity, rgw::IAM::s3BypassGovernanceRetention, obj_arn);
-        if (r == Effect::Deny) {
-          bypass_perm = false;
-        }
-      } else if (r == Effect::Pass && !s->session_policies.empty()) {
-        r = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                               rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key(), s->object->get_name()));
-        if (r == Effect::Deny) {
-          bypass_perm = false;
-        }
-      }
-    }
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                              s->object->get_instance().empty() ?
-                                              rgw::IAM::s3DeleteObject :
-                                              rgw::IAM::s3DeleteObjectVersion,
-                                              ARN(s->bucket->get_key(), s->object->get_name()));
-    if (identity_policy_res == Effect::Deny) {
-      return -EACCES;
-    }
+  if (has_s3_existing_tag || has_s3_resource_tag)
+    rgw_iam_add_objtags(this, s, has_s3_existing_tag, has_s3_resource_tag);
 
-    rgw::IAM::Effect r = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    ARN obj_arn(ARN(s->bucket->get_key(), s->object->get_name()));
-    if (s->iam_policy) {
-      r = s->iam_policy->eval(s->env, *s->auth.identity,
-                                s->object->get_instance().empty() ?
-                                rgw::IAM::s3DeleteObject :
-                                rgw::IAM::s3DeleteObjectVersion,
-                                obj_arn,
-         princ_type);
-    }
-    if (r == Effect::Deny)
-      return -EACCES;
+  const auto arn = ARN{s->object->get_obj()};
+  const auto action = s->object->get_instance().empty() ?
+      rgw::IAM::s3DeleteObject :
+      rgw::IAM::s3DeleteObjectVersion;
 
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              s->object->get_instance().empty() ?
-                                              rgw::IAM::s3DeleteObject :
-                                              rgw::IAM::s3DeleteObjectVersion,
-                                              obj_arn);
-      if (session_policy_res == Effect::Deny) {
-          return -EACCES;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && r == Effect::Allow)) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || r == Effect::Allow) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
-          return 0;
-        }
-      }
-      return -EACCES;
-    }
-    if (r == Effect::Allow || identity_policy_res == Effect::Allow)
-      return 0;
+  if (!verify_bucket_permission(this, s, arn, action)) {
+    return -EACCES;
   }
 
-  if (!verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
-    return -EACCES;
+  if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) {
+    // require s3BypassGovernanceRetention for x-amz-bypass-governance-retention
+    bypass_perm = verify_bucket_permission(this, s, arn, rgw::IAM::s3BypassGovernanceRetention);
   }
 
   if (s->bucket->get_info().mfa_enabled() &&
@@ -5585,76 +5395,31 @@ int RGWCopyObj::verify_permission(optional_yield y)
       }
     }
 
-    /* admin request overrides permission checks */
-    if (!s->auth.identity->is_admin_of(src_acl.get_owner().id)) {
-      if (src_policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-        auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, src_policy, s->iam_identity_policies, s->session_policies);
-        if (has_s3_existing_tag || has_s3_resource_tag)
-          rgw_iam_add_objtags(this, s, s->src_object.get(), has_s3_existing_tag, has_s3_resource_tag);
-
-        ARN obj_arn(s->src_object->get_obj());
-        auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                                  s->src_object->get_instance().empty() ?
-                                                  rgw::IAM::s3GetObject :
-                                                  rgw::IAM::s3GetObjectVersion,
-                                                  obj_arn);
-        if (identity_policy_res == Effect::Deny) {
-          return -EACCES;
-        }
-        auto e = Effect::Pass;
-        rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-        if (src_policy) {
-               e = src_policy->eval(s->env, *s->auth.identity,
-            s->src_object->get_instance().empty() ?
-            rgw::IAM::s3GetObject :
-            rgw::IAM::s3GetObjectVersion,
-            obj_arn,
-            princ_type);
-        }
-       if (e == Effect::Deny) {
-         return -EACCES;
-       }
-        if (!s->session_policies.empty()) {
-         auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                                  s->src_object->get_instance().empty() ?
-                                                  rgw::IAM::s3GetObject :
-                                                  rgw::IAM::s3GetObjectVersion,
-                                                  obj_arn);
-        if (session_policy_res == Effect::Deny) {
-            return -EACCES;
-        }
-        if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-          //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-          if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) &&
-              (session_policy_res != Effect::Allow || e != Effect::Allow)) {
-            return -EACCES;
-          }
-        } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-          //Intersection of session policy and identity policy plus bucket policy
-          if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) && e != Effect::Allow) {
-            return -EACCES;
-          }
-        } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-          if (session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) {
-            return -EACCES;
-          }
-        }
-      }
-  if (identity_policy_res == Effect::Pass && e == Effect::Pass &&
-                  !src_acl.verify_permission(this, *s->auth.identity, s->perm_mask,
-                                             RGW_PERM_READ)) { 
-         return -EACCES;
-       }
-      //remove src object tags as it may interfere with policy evaluation of destination obj
-      if (has_s3_existing_tag || has_s3_resource_tag)
-        rgw_iam_remove_objtags(this, s, s->src_object.get(), has_s3_existing_tag, has_s3_resource_tag);
-
-      } else if (!src_acl.verify_permission(this, *s->auth.identity,
-                                              s->perm_mask,
-                                           RGW_PERM_READ)) {
-       return -EACCES;
-      }
+    RGWAccessControlPolicy src_bucket_acl;
+    op_ret = rgw_op_get_bucket_policy_from_attr(this, s->cct, driver,
+                                                src_bucket->get_owner(),
+                                                src_bucket->get_attrs(),
+                                                src_bucket_acl, y);
+    if (op_ret < 0) {
+      return op_ret;
+    }
+
+    auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, src_policy, s->iam_identity_policies, s->session_policies);
+    if (has_s3_existing_tag || has_s3_resource_tag)
+      rgw_iam_add_objtags(this, s, s->src_object.get(), has_s3_existing_tag, has_s3_resource_tag);
+
+    const auto action = s->src_object->get_instance().empty() ?
+        rgw::IAM::s3GetObject :
+        rgw::IAM::s3GetObjectVersion;
+
+    if (!verify_bucket_permission(this, s, ARN(s->src_object->get_obj()),
+                                  s->user_acl, src_bucket_acl,
+                                  src_policy, s->iam_identity_policies,
+                                  s->session_policies, action)) {
+      return -EACCES;
     }
+
+    rgw_iam_remove_objtags(this, s, s->src_object.get(), has_s3_existing_tag, has_s3_resource_tag);
   }
 
   RGWAccessControlPolicy dest_bucket_policy;
@@ -5669,73 +5434,20 @@ int RGWCopyObj::verify_permission(optional_yield y)
     return op_ret;
   }
   auto dest_iam_policy = get_iam_policy_from_attr(s->cct, s->bucket->get_attrs());
-  /* admin request overrides permission checks */
-  if (! s->auth.identity->is_admin_of(dest_policy.get_owner().id)){
-    if (dest_iam_policy != boost::none || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-      //Add destination bucket tags for authorization
-      auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, dest_iam_policy, s->iam_identity_policies, s->session_policies);
-      if (has_s3_resource_tag)
-        rgw_iam_add_buckettags(this, s, s->bucket.get());
-
-      rgw_add_to_iam_environment(s->env, "s3:x-amz-copy-source", copy_source);
-      if (md_directive)
-       rgw_add_to_iam_environment(s->env, "s3:x-amz-metadata-directive",
-                                  *md_directive);
-
-      ARN obj_arn(s->object->get_obj());
-      auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies,
-                                                                  s->env,
-                                                                  rgw::IAM::s3PutObject,
-                                                                  obj_arn);
-      if (identity_policy_res == Effect::Deny) {
-        return -EACCES;
-      }
-      auto e = Effect::Pass;
-      rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-      if (dest_iam_policy) {
-        e = dest_iam_policy->eval(s->env, *s->auth.identity,
-                                      rgw::IAM::s3PutObject,
-                                      obj_arn,
-                                      princ_type);
-      }
-      if (e == Effect::Deny) {
-        return -EACCES;
-      }
-      if (!s->session_policies.empty()) {
-        auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                                                   rgw::IAM::s3PutObject, obj_arn);
-        if (session_policy_res == Effect::Deny) {
-            return false;
-        }
-        if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-          //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-          if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) &&
-              (session_policy_res != Effect::Allow || e == Effect::Allow)) {
-            return -EACCES;
-          }
-        } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-          //Intersection of session policy and identity policy plus bucket policy
-          if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) && e != Effect::Allow) {
-            return -EACCES;
-          }
-        } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-          if (session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) {
-            return -EACCES;
-          }
-        }
-      }
-      if (identity_policy_res == Effect::Pass && e == Effect::Pass &&
-                 ! dest_bucket_policy.verify_permission(this,
-                                                        *s->auth.identity,
-                                                        s->perm_mask,
-                                                        RGW_PERM_WRITE)){
-        return -EACCES;
-      }
-    } else if (! dest_bucket_policy.verify_permission(this, *s->auth.identity, s->perm_mask,
-                                                      RGW_PERM_WRITE)) {
-      return -EACCES;
-    }
 
+  //Add destination bucket tags for authorization
+  auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, dest_iam_policy, s->iam_identity_policies, s->session_policies);
+  if (has_s3_resource_tag)
+    rgw_iam_add_buckettags(this, s, s->bucket.get());
+
+  rgw_add_to_iam_environment(s->env, "s3:x-amz-copy-source", copy_source);
+  if (md_directive)
+    rgw_add_to_iam_environment(s->env, "s3:x-amz-metadata-directive",
+                               *md_directive);
+
+  if (!verify_bucket_permission(this, s, ARN(s->object->get_obj()),
+                                rgw::IAM::s3PutObject)) {
+    return -EACCES;
   }
 
   op_ret = init_dest_policy();
@@ -6523,58 +6235,7 @@ int RGWInitMultipart::verify_permission(optional_yield y)
   // add server-side encryption headers
   rgw_iam_add_crypt_attrs(s->env, s->info.crypt_attribute_map);
 
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                              rgw::IAM::s3PutObject,
-                                              s->object->get_obj());
-    if (identity_policy_res == Effect::Deny) {
-      return -EACCES;
-    }
-
-    rgw::IAM::Effect e = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    ARN obj_arn(s->object->get_obj());
-    if (s->iam_policy) {
-      e = s->iam_policy->eval(s->env, *s->auth.identity,
-                                rgw::IAM::s3PutObject,
-                                obj_arn,
-         princ_type);
-    }
-    if (e == Effect::Deny) {
-      return -EACCES;
-    }
-
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              rgw::IAM::s3PutObject,
-                                              s->object->get_obj());
-      if (session_policy_res == Effect::Deny) {
-          return -EACCES;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
-          return 0;
-        }
-      }
-      return -EACCES;
-    }
-    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
-      return 0;
-    }
-  }
-
-  if (!verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
+  if (!verify_bucket_permission(this, s, rgw::IAM::s3PutObject)) {
     return -EACCES;
   }
 
@@ -6644,58 +6305,8 @@ int RGWCompleteMultipart::verify_permission(optional_yield y)
   // add server-side encryption headers
   rgw_iam_add_crypt_attrs(s->env, s->info.crypt_attribute_map);
 
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || ! s->session_policies.empty()) {
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                              rgw::IAM::s3PutObject,
-                                              s->object->get_obj());
-    if (identity_policy_res == Effect::Deny) {
-      return -EACCES;
-    }
-
-    rgw::IAM::Effect e = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    rgw::ARN obj_arn(s->object->get_obj());
-    if (s->iam_policy) {
-      e = s->iam_policy->eval(s->env, *s->auth.identity,
-                                rgw::IAM::s3PutObject,
-                                obj_arn,
-         princ_type);
-    }
-    if (e == Effect::Deny) {
-      return -EACCES;
-    }
-
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              rgw::IAM::s3PutObject,
-                                              s->object->get_obj());
-      if (session_policy_res == Effect::Deny) {
-          return -EACCES;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
-          return 0;
-        }
-      }
-      return -EACCES;
-    }
-    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
-      return 0;
-    }
-  }
-
-  if (!verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
+  if (!verify_bucket_permission(this, s, ARN(s->object->get_obj()),
+                                rgw::IAM::s3PutObject)) {
     return -EACCES;
   }
 
@@ -6926,58 +6537,8 @@ int RGWAbortMultipart::verify_permission(optional_yield y)
   if (has_s3_existing_tag || has_s3_resource_tag)
     rgw_iam_add_objtags(this, s, has_s3_existing_tag, has_s3_resource_tag);
 
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                              rgw::IAM::s3AbortMultipartUpload,
-                                              s->object->get_obj());
-    if (identity_policy_res == Effect::Deny) {
-      return -EACCES;
-    }
-
-    rgw::IAM::Effect e = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    ARN obj_arn(s->object->get_obj());
-    if (s->iam_policy) {
-      e = s->iam_policy->eval(s->env, *s->auth.identity,
-                                rgw::IAM::s3AbortMultipartUpload,
-                                obj_arn, princ_type);
-    }
-
-    if (e == Effect::Deny) {
-      return -EACCES;
-    }
-
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              rgw::IAM::s3PutObject,
-                                              s->object->get_obj());
-      if (session_policy_res == Effect::Deny) {
-          return -EACCES;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
-          return 0;
-        }
-      }
-      return -EACCES;
-    }
-    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
-      return 0;
-    }
-  }
-
-  if (!verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
+  if (!verify_bucket_permission(this, s, ARN(s->object->get_obj()),
+                                rgw::IAM::s3AbortMultipartUpload)) {
     return -EACCES;
   }
 
@@ -7120,99 +6681,27 @@ void RGWGetHealthCheck::execute(optional_yield y)
   }
 }
 
-int RGWDeleteMultiObj::verify_permission(optional_yield y)
+int RGWDeleteMultiObj::init_processing(optional_yield y)
 {
-  int op_ret = get_params(y);
-  if (op_ret) {
-    return op_ret;
+  int ret = get_params(y);
+  if (ret) {
+    return ret;
   }
 
-  auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, s);
-    if (has_s3_existing_tag || has_s3_resource_tag)
-      rgw_iam_add_objtags(this, s, has_s3_existing_tag, has_s3_resource_tag);
-
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || ! s->session_policies.empty()) {
-    if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) {
-      ARN bucket_arn(s->bucket->get_key());
-      auto r = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                               rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key()));
-      if (r == Effect::Deny) {
-        bypass_perm = false;
-      } else if (r == Effect::Pass && s->iam_policy) {
-        r = s->iam_policy->eval(s->env, *s->auth.identity, rgw::IAM::s3BypassGovernanceRetention,
-                                     bucket_arn);
-        if (r == Effect::Deny) {
-          bypass_perm = false;
-        }
-      } else if (r == Effect::Pass && !s->session_policies.empty()) {
-        r = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                               rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key()));
-        if (r == Effect::Deny) {
-          bypass_perm = false;
-        }
-      }
-    }
-
-    bool not_versioned = rgw::sal::Object::empty(s->object.get()) || s->object->get_instance().empty();
-
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                              not_versioned ?
-                                              rgw::IAM::s3DeleteObject :
-                                              rgw::IAM::s3DeleteObjectVersion,
-                                              ARN(s->bucket->get_key()));
-    if (identity_policy_res == Effect::Deny) {
-      return -EACCES;
-    }
+  return RGWOp::init_processing(y);
+}
 
-    rgw::IAM::Effect r = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    rgw::ARN bucket_arn(s->bucket->get_key());
-    if (s->iam_policy) {
-      r = s->iam_policy->eval(s->env, *s->auth.identity,
-                                not_versioned ?
-                                rgw::IAM::s3DeleteObject :
-                                rgw::IAM::s3DeleteObjectVersion,
-                                bucket_arn,
-         princ_type);
-    }
-    if (r == Effect::Deny)
-      return -EACCES;
+int RGWDeleteMultiObj::verify_permission(optional_yield y)
+{
+  auto [has_s3_existing_tag, has_s3_resource_tag] = rgw_check_policy_condition(this, s);
+  if (has_s3_existing_tag || has_s3_resource_tag)
+    rgw_iam_add_objtags(this, s, has_s3_existing_tag, has_s3_resource_tag);
 
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              not_versioned ?
-                                              rgw::IAM::s3DeleteObject :
-                                              rgw::IAM::s3DeleteObjectVersion,
-                                              ARN(s->bucket->get_key()));
-      if (session_policy_res == Effect::Deny) {
-          return -EACCES;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && r == Effect::Allow)) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || r == Effect::Allow) {
-          return 0;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
-          return 0;
-        }
-      }
-      return -EACCES;
-    }
-    if (r == Effect::Allow || identity_policy_res == Effect::Allow)
-      return 0;
+  if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) {
+    // require s3BypassGovernanceRetention for x-amz-bypass-governance-retention
+    bypass_perm = verify_bucket_permission(this, s, rgw::IAM::s3BypassGovernanceRetention);
   }
 
-  acl_allowed = verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE);
-  if (!acl_allowed)
-    return -EACCES;
-
   return 0;
 }
 
@@ -7255,73 +6744,22 @@ void RGWDeleteMultiObj::wait_flush(optional_yield y,
 void RGWDeleteMultiObj::handle_individual_object(const rgw_obj_key& o, optional_yield y,
                                                  boost::asio::deadline_timer *formatter_flush_cond)
 {
-  std::string version_id;
   std::unique_ptr<rgw::sal::Object> obj = bucket->get_object(o);
-  if (s->iam_policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                                                 o.instance.empty() ?
-                                                                 rgw::IAM::s3DeleteObject :
-                                                                 rgw::IAM::s3DeleteObjectVersion,
-                                                                 ARN(obj->get_obj()));
-    if (identity_policy_res == Effect::Deny) {
-      send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-      return;
-    }
-
-    rgw::IAM::Effect e = Effect::Pass;
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    if (s->iam_policy) {
-      ARN obj_arn(obj->get_obj());
-      e = s->iam_policy->eval(s->env,
-                              *s->auth.identity,
-                              o.instance.empty() ?
-                              rgw::IAM::s3DeleteObject :
-                              rgw::IAM::s3DeleteObjectVersion,
-                              obj_arn,
-                              princ_type);
-    }
-    if (e == Effect::Deny) {
-      send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-      return;
-    }
-
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                                                  o.instance.empty() ?
-                                                                  rgw::IAM::s3DeleteObject :
-                                                                  rgw::IAM::s3DeleteObjectVersion,
-                                                                  ARN(obj->get_obj()));
-      if (session_policy_res == Effect::Deny) {
-        send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-        return;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) &&
-            (session_policy_res != Effect::Allow || e != Effect::Allow)) {
-          send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-          return;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) && e != Effect::Allow) {
-          send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-          return;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) {
-          send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-          return;
-        }
-      }
-      send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-      return;
-    }
+  if (o.empty()) {
+    send_partial_response(o, false, "", -EINVAL, formatter_flush_cond);
+    return;
+  }
 
-    if ((identity_policy_res == Effect::Pass && e == Effect::Pass && !acl_allowed)) {
-      send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
-      return;
-    }
+  // verify object delete permission
+  const auto action = o.instance.empty() ?
+      rgw::IAM::s3DeleteObject :
+      rgw::IAM::s3DeleteObjectVersion;
+  if (!verify_bucket_permission(this, s, ARN(obj->get_obj()), s->user_acl,
+                                s->bucket_acl, s->iam_policy,
+                                s->iam_identity_policies,
+                                s->session_policies, action)) {
+    send_partial_response(o, false, "", -EACCES, formatter_flush_cond);
+    return;
   }
 
   uint64_t obj_size = 0;
@@ -7371,6 +6809,7 @@ void RGWDeleteMultiObj::handle_individual_object(const rgw_obj_key& o, optional_
 
   obj->set_atomic();
 
+  std::string version_id; // empty
   std::unique_ptr<rgw::sal::Object::DeleteOp> del_op = obj->get_delete_op();
   del_op->params.versioning_status = obj->get_bucket()->get_info().versioning_status();
   del_op->params.obj_owner = s->owner;
@@ -7853,53 +7292,9 @@ bool RGWBulkUploadOp::handle_file_verify_permission(RGWBucketInfo& binfo,
 
   auto policy = get_iam_policy_from_attr(s->cct, battrs);
 
-  bucket_owner = bacl.get_owner();
-  if (policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
-    auto identity_policy_res = eval_identity_or_session_policies(this, s->iam_identity_policies, s->env,
-                                              rgw::IAM::s3PutObject, obj);
-    if (identity_policy_res == Effect::Deny) {
-      return false;
-    }
-
-    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
-    ARN obj_arn(obj);
-    auto e = policy->eval(s->env, *s->auth.identity,
-                         rgw::IAM::s3PutObject, obj_arn, princ_type);
-    if (e == Effect::Deny) {
-      return false;
-    }
-  
-    if (!s->session_policies.empty()) {
-      auto session_policy_res = eval_identity_or_session_policies(this, s->session_policies, s->env,
-                                              rgw::IAM::s3PutObject, obj);
-      if (session_policy_res == Effect::Deny) {
-          return false;
-      }
-      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
-        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
-            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
-          return true;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
-        //Intersection of session policy and identity policy plus bucket policy
-        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
-          return true;
-        }
-      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
-        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
-          return true;
-        }
-      }
-      return false;
-    }
-    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
-      return true;
-    }
-  }
-    
-  return verify_bucket_permission_no_policy(this, s, s->user_acl,
-                                           bacl, RGW_PERM_WRITE);
+  return verify_bucket_permission(this, s, ARN(obj), s->user_acl, bacl, policy,
+                                  s->iam_identity_policies, s->session_policies,
+                                  rgw::IAM::s3PutObject);
 }
 
 int RGWBulkUploadOp::handle_file(const std::string_view path,
index 9302017fc3efd54720eac7bea6c2c6bdae95846d..5f947fd53c5e21a81a7458a4814359dc12a4bbbb 100644 (file)
@@ -1322,6 +1322,7 @@ public:
     attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
   }
 
+  int init_processing(optional_yield y) override;
   int verify_permission(optional_yield y) override;
   void pre_exec() override;
   void execute(optional_yield y) override;
@@ -1446,6 +1447,7 @@ public:
       bypass_governance_mode(false) {
   }
 
+  int init_processing(optional_yield y) override;
   int verify_permission(optional_yield y) override;
   void pre_exec() override;
   void execute(optional_yield y) override;
@@ -2023,7 +2025,6 @@ protected:
   rgw::sal::Bucket* bucket;
   bool quiet;
   bool status_dumped;
-  bool acl_allowed = false;
   bool bypass_perm;
   bool bypass_governance_mode;
 
@@ -2035,6 +2036,7 @@ public:
     bypass_governance_mode = false;
   }
 
+  int init_processing(optional_yield y) override;
   int verify_permission(optional_yield y) override;
   void pre_exec() override;
   void execute(optional_yield y) override;
index fa92f2ec88561c83232b1eb23689dcb6d924fdba..bde5925dfd1a91759fef5db470d66b13e2235b9c 100644 (file)
@@ -2407,6 +2407,16 @@ int RGWFormPost::get_data(ceph::bufferlist& bl, bool& again)
   return bl.length();
 }
 
+// override error_handler() to map error messages from abort_early(), which
+// doesn't end up calling our send_response()
+int RGWFormPost::error_handler(int err_no, std::string *error_content, optional_yield y)
+{
+  if (!err_msg.empty()) {
+    *error_content = err_msg;
+  }
+  return err_no;
+}
+
 void RGWFormPost::send_response()
 {
   std::string redirect = get_part_str(ctrl_parts, "redirect");
index 18c80aea402586bf9e2f99d5e50b8281ab92d2c5..eb1c4422e34b85943d023726b273b0b2a7cf4031 100644 (file)
@@ -274,6 +274,7 @@ public:
 
   int get_params(optional_yield y) override;
   int get_data(ceph::bufferlist& bl, bool& again) override;
+  int error_handler(int err_no, std::string *error_content, optional_yield y) override;
   void send_response() override;
 
   static bool is_formpost_req(req_state* const s);