]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/acl/s3: parse_policy() as free function
authorCasey Bodley <cbodley@redhat.com>
Sat, 18 Nov 2023 02:29:25 +0000 (21:29 -0500)
committerCasey Bodley <cbodley@redhat.com>
Thu, 30 Nov 2023 16:24:59 +0000 (11:24 -0500)
s3 acl parsing classes no longer inherit from the acl classes
themselves, and are all encapsulated in rgw_acl_s3.cc behind a single
rgw::s3::parse_policy() function

Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/driver/rados/rgw_bucket.cc
src/rgw/rgw_acl.cc
src/rgw/rgw_acl.h
src/rgw/rgw_acl_s3.cc
src/rgw/rgw_acl_s3.h
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h

index 6cbcbeae9a2b030c4f0e16a9b583a146e98044e1..64d8e31cc3cc6af1b7813ef7f1c8dd5d08c6468b 100644 (file)
@@ -972,7 +972,7 @@ int RGWBucketAdminOp::get_policy(rgw::sal::Driver* driver, RGWBucketAdminOpState
 int RGWBucketAdminOp::dump_s3_policy(rgw::sal::Driver* driver, RGWBucketAdminOpState& op_state,
                   ostream& os, const DoutPrefixProvider *dpp, optional_yield y)
 {
-  RGWAccessControlPolicy_S3 policy;
+  RGWAccessControlPolicy policy;
 
   int ret = get_policy(driver, op_state, policy, dpp, y);
   if (ret < 0)
index 6e3aafe762ad83c524e59aa0e0c69f5f49cb2b38..316af76ecf054071180ef098852e1fda3e4fc877 100644 (file)
@@ -419,9 +419,9 @@ void RGWAccessControlPolicy::dump(Formatter *f) const
   encode_json("owner", owner, f);
 }
 
-ACLGroupTypeEnum ACLGrant::uri_to_group(string& uri)
+ACLGroupTypeEnum ACLGrant::uri_to_group(std::string_view uri)
 {
   // this is required for backward compatibility
-  return ACLGrant_S3::uri_to_group(uri);
+  return rgw::s3::acl_uri_to_group(uri);
 }
 
index c69ee88404e3a0531cc25d0774a629753093fdf3..afa63d8cdfb36d337714d5ad3dd9db07052492d8 100644 (file)
@@ -111,7 +111,7 @@ public:
   void dump(Formatter *f) const;
   static void generate_test_instances(std::list<ACLGrant*>& o);
 
-  ACLGroupTypeEnum uri_to_group(std::string& uri);
+  static ACLGroupTypeEnum uri_to_group(std::string_view uri);
 
   void set_canon(const rgw_user& _id, const std::string& _name, const uint32_t perm) {
     type.set(ACL_TYPE_CANON_USER);
index f663e38309219e973fa232fbca25aa9bc728f620..f4e4221f2c0b609ab6ba03eccf4d5f4d9a14873d 100644 (file)
@@ -25,6 +25,14 @@ using namespace std;
 static string rgw_uri_all_users = RGW_URI_ALL_USERS;
 static string rgw_uri_auth_users = RGW_URI_AUTH_USERS;
 
+class ACLPermission_S3 : public XMLObj
+{
+public:
+  uint32_t flags = 0;
+
+  bool xml_end(const char *el) override;
+};
+
 void to_xml(ACLPermission perm, std::ostream& out)
 {
   const uint32_t flags = perm.get_permissions();
@@ -42,8 +50,7 @@ void to_xml(ACLPermission perm, std::ostream& out)
   }
 }
 
-bool ACLPermission_S3::
-xml_end(const char *el)
+bool ACLPermission_S3::xml_end(const char *el)
 {
   const char *s = data.c_str();
   if (strcasecmp(s, "READ") == 0) {
@@ -97,6 +104,15 @@ public:
   }
 };
 
+class ACLGrantee_S3 : public XMLObj
+{
+public:
+  ACLGrantee_S3() {}
+  virtual ~ACLGrantee_S3() override {}
+
+  bool xml_start(const char *el, const char **attr);
+};
+
 class ACLID_S3 : public XMLObj
 {
 public:
@@ -126,6 +142,15 @@ public:
  ~ACLDisplayName_S3() override {}
 };
 
+class ACLOwner_S3 : public XMLObj
+{
+public:
+  std::string id;
+  std::string display_name;
+
+  bool xml_end(const char *el) override;
+};
+
 bool ACLOwner_S3::xml_end(const char *el) {
   ACLID_S3 *acl_id = static_cast<ACLID_S3 *>(find_first("ID"));
   ACLID_S3 *acl_name = static_cast<ACLID_S3 *>(find_first("DisplayName"));
@@ -156,12 +181,25 @@ void to_xml(const ACLOwner& o, std::ostream& out)
   out << "</Owner>";
 }
 
+class ACLGrant_S3 : public XMLObj
+{
+public:
+  ACLGranteeType type;
+  std::string id;
+  std::string name;
+  std::string uri;
+  std::string email;
+  ACLPermission_S3* permission = nullptr;
+
+  bool xml_end(const char *el) override;
+  bool xml_start(const char *el, const char **attr);
+};
+
 bool ACLGrant_S3::xml_end(const char *el) {
   ACLGrantee_S3 *acl_grantee;
   ACLID_S3 *acl_id;
   ACLURI_S3 *acl_uri;
   ACLEmail_S3 *acl_email;
-  ACLPermission_S3 *acl_permission;
   ACLDisplayName_S3 *acl_name;
   string uri;
 
@@ -171,17 +209,12 @@ bool ACLGrant_S3::xml_end(const char *el) {
   string type_str;
   if (!acl_grantee->get_attr("xsi:type", type_str))
     return false;
-  ACLGranteeType_S3::set(type_str.c_str(), type);
-  
-  acl_permission = static_cast<ACLPermission_S3 *>(find_first("Permission"));
-  if (!acl_permission)
-    return false;
 
-  permission = *acl_permission;
+  ACLGranteeType_S3::set(type_str.c_str(), type);
 
-  id.clear();
-  name.clear();
-  email.clear();
+  permission = static_cast<ACLPermission_S3*>(find_first("Permission"));
+  if (!permission)
+    return false;
 
   switch (type.get_type()) {
   case ACL_TYPE_CANON_USER:
@@ -198,7 +231,6 @@ bool ACLGrant_S3::xml_end(const char *el) {
     if (!acl_uri)
       return false;
     uri = acl_uri->get_data();
-    group = uri_to_group(uri);
     break;
   case ACL_TYPE_EMAIL_USER:
     acl_email = static_cast<ACLEmail_S3 *>(acl_grantee->find_first("EmailAddress"));
@@ -236,7 +268,7 @@ void to_xml(const ACLGrant& grant, ostream& out)
     out << "<EmailAddress>" << grant.email << "</EmailAddress>";
     break;
   case ACL_TYPE_GROUP:
-    if (!ACLGrant_S3::group_to_uri(grant.group, uri)) {
+    if (!rgw::s3::acl_group_to_uri(grant.group, uri)) {
       break;
     }
     out << "<URI>" << uri << "</URI>";
@@ -249,27 +281,13 @@ void to_xml(const ACLGrant& grant, ostream& out)
   out << "</Grant>";
 }
 
-bool ACLGrant_S3::group_to_uri(ACLGroupTypeEnum group, string& uri)
+class RGWAccessControlList_S3 : public XMLObj
 {
-  switch (group) {
-  case ACL_GROUP_ALL_USERS:
-    uri = rgw_uri_all_users;
-    return true;
-  case ACL_GROUP_AUTHENTICATED_USERS:
-    uri = rgw_uri_auth_users;
-    return true;
-  default:
-    return false;
-  }
-}
+public:
+  bool xml_end(const char *el) override;
+};
 
 bool RGWAccessControlList_S3::xml_end(const char *el) {
-  XMLObjIter iter = find("Grant");
-  ACLGrant_S3 *grant = static_cast<ACLGrant_S3 *>(iter.get_next());
-  while (grant) {
-    add_grant(*grant);
-    grant = static_cast<ACLGrant_S3 *>(iter.get_next());
-  }
   return true;
 }
 
@@ -318,7 +336,7 @@ static int parse_grantee_str(const DoutPrefixProvider* dpp,
 
     grant.set_canon(user->get_id(), user->get_display_name(), rgw_perm);
   } else if (strcasecmp(id_type.c_str(), "uri") == 0) {
-    ACLGroupTypeEnum gid = grant.uri_to_group(id_val);
+    ACLGroupTypeEnum gid = rgw::s3::acl_uri_to_group(id_val);
     if (gid == ACL_GROUP_NONE)
       return -EINVAL;
 
@@ -401,18 +419,21 @@ static int create_canned(const ACLOwner& owner, const ACLOwner& bucket_owner,
   return 0;
 }
 
+class RGWAccessControlPolicy_S3 : public XMLObj
+{
+public:
+  bool xml_end(const char *el) override;
+};
+
 bool RGWAccessControlPolicy_S3::xml_end(const char *el) {
   RGWAccessControlList_S3 *s3acl =
       static_cast<RGWAccessControlList_S3 *>(find_first("AccessControlList"));
   if (!s3acl)
     return false;
 
-  acl = *s3acl;
-
-  ACLOwner *owner_p = static_cast<ACLOwner_S3 *>(find_first("Owner"));
+  ACLOwner_S3 *owner_p = static_cast<ACLOwner_S3 *>(find_first("Owner"));
   if (!owner_p)
     return false;
-  owner = *owner_p;
   return true;
 }
 
@@ -433,117 +454,68 @@ static const s3_acl_header acl_header_perms[] = {
   {0, NULL}
 };
 
-/*
-  can only be called on object that was parsed
- */
-int RGWAccessControlPolicy_S3::rebuild(const DoutPrefixProvider *dpp,
-                                      rgw::sal::Driver* driver, ACLOwner *owner,
-                                      RGWAccessControlPolicy& dest, std::string &err_msg)
+static int resolve_grant(const DoutPrefixProvider* dpp, optional_yield y,
+                         rgw::sal::Driver* driver, ACLGrant_S3& xml_grant,
+                         ACLGrant& grant, std::string& err_msg)
 {
-  if (!owner || owner->id.empty()) {
-    return -EINVAL;
-  }
+  const uint32_t perm = xml_grant.permission->flags;
 
-  ACLOwner *requested_owner = static_cast<ACLOwner_S3 *>(find_first("Owner"));
-  if (requested_owner && requested_owner->id != owner->id) {
-    return -EPERM;
-  }
+  std::unique_ptr<rgw::sal::User> user;
+  switch (xml_grant.type.get_type()) {
+  case ACL_TYPE_EMAIL_USER:
+    if (xml_grant.email.empty()) {
+      return -EINVAL;
+    }
+    if (driver->get_user_by_email(dpp, xml_grant.email, y, &user) < 0) {
+      ldpp_dout(dpp, 10) << "grant user email not found or other error" << dendl;
+      err_msg = "The e-mail address you provided does not match any account on record.";
+      return -ERR_UNRESOLVABLE_EMAIL;
+    }
+    grant.set_canon(user->get_id(), user->get_display_name(), perm);
+    return 0;
 
-  std::unique_ptr<rgw::sal::User> user = driver->get_user(owner->id);
-  if (user->load_user(dpp, null_yield) < 0) {
-    ldpp_dout(dpp, 10) << "owner info does not exist" << dendl;
-    err_msg = "Invalid id";
-    return -EINVAL;
-  }
-  ACLOwner& dest_owner = dest.get_owner();
-  dest_owner.id = owner->id;
-  dest_owner.display_name = user->get_display_name();
-
-  ldpp_dout(dpp, 20) << "owner id=" << owner->id << dendl;
-  ldpp_dout(dpp, 20) << "dest owner id=" << dest.get_owner().id << dendl;
-
-  RGWAccessControlList& dst_acl = dest.get_acl();
-
-  multimap<string, ACLGrant>& grant_map = acl.get_grant_map();
-  multimap<string, ACLGrant>::iterator iter;
-  for (iter = grant_map.begin(); iter != grant_map.end(); ++iter) {
-    ACLGrant& src_grant = iter->second;
-    ACLGranteeType type = src_grant.get_type();
-    ACLGrant new_grant;
-    bool grant_ok = false;
-    rgw_user uid;
-    RGWUserInfo grant_user;
-    switch (type.get_type()) {
-    case ACL_TYPE_EMAIL_USER:
-      {
-        string email;
-        rgw_user u;
-        if (!src_grant.get_id(u)) {
-          ldpp_dout(dpp, 0) << "ERROR: src_grant.get_id() failed" << dendl;
-          return -EINVAL;
-        }
-        email = u.id;
-        ldpp_dout(dpp, 10) << "grant user email=" << email << dendl;
-       if (driver->get_user_by_email(dpp, email, null_yield, &user) < 0) {
-          ldpp_dout(dpp, 10) << "grant user email not found or other error" << dendl;
-          err_msg = "The e-mail address you provided does not match any account on record.";
-          return -ERR_UNRESOLVABLE_EMAIL;
-        }
-       grant_user = user->get_info();
-        uid = grant_user.user_id;
-      }
-    case ACL_TYPE_CANON_USER:
-      {
-        if (type.get_type() == ACL_TYPE_CANON_USER) {
-          if (!src_grant.get_id(uid)) {
-            ldpp_dout(dpp, 0) << "ERROR: src_grant.get_id() failed" << dendl;
-            err_msg = "Invalid id";
-            return -EINVAL;
-          }
-        }
-    
-        if (grant_user.user_id.empty()) {
-         user = driver->get_user(uid);
-         if (user->load_user(dpp, null_yield) < 0) {
-           ldpp_dout(dpp, 10) << "grant user does not exist:" << uid << dendl;
-           err_msg = "Invalid id";
-           return -EINVAL;
-         } else {
-           grant_user = user->get_info();
-         }
-        }
-       ACLPermission perm = src_grant.get_permission();
-       new_grant.set_canon(uid, grant_user.display_name, perm.get_permissions());
-       grant_ok = true;
-       rgw_user new_id;
-       new_grant.get_id(new_id);
-       ldpp_dout(dpp, 10) << "new grant: " << new_id << ":" << grant_user.display_name << dendl;
-      }
-      break;
-    case ACL_TYPE_GROUP:
-      {
-        string uri;
-        if (ACLGrant_S3::group_to_uri(src_grant.get_group(), uri)) {
-          new_grant = src_grant;
-          grant_ok = true;
-          ldpp_dout(dpp, 10) << "new grant: " << uri << dendl;
-        } else {
-          ldpp_dout(dpp, 10) << "bad grant group:" << (int)src_grant.get_group() << dendl;
-          err_msg = "Invalid group uri";
-          return -EINVAL;
-        }
-      }
-    default:
-      break;
+  case ACL_TYPE_CANON_USER:
+    user = driver->get_user(rgw_user{xml_grant.id});
+    if (user->load_user(dpp, y) < 0) {
+      ldpp_dout(dpp, 10) << "grant user does not exist: " << xml_grant.id << dendl;
+      err_msg = "Invalid CanonicalUser id";
+      return -EINVAL;
     }
-    if (grant_ok) {
-      dst_acl.add_grant(new_grant);
+    grant.set_canon(user->get_id(), user->get_display_name(), perm);
+    return 0;
+
+  case ACL_TYPE_GROUP:
+    if (const auto group = rgw::s3::acl_uri_to_group(xml_grant.uri);
+        group != ACL_GROUP_NONE) {
+      grant.set_group(group, perm);
+      return 0;
+    } else {
+      ldpp_dout(dpp, 10) << "bad grant group: " << xml_grant.uri << dendl;
+      err_msg = "Invalid group uri";
+      return -EINVAL;
     }
-  }
 
-  return 0; 
+  case ACL_TYPE_REFERER:
+  case ACL_TYPE_UNKNOWN:
+  default:
+    err_msg = "Invalid Grantee type";
+    return -EINVAL;
+  }
 }
 
+/**
+ * Interfaces with the webserver's XML handling code
+ * to parse it in a way that makes sense for the rgw.
+ */
+class RGWACLXMLParser_S3 : public RGWXMLParser
+{
+  CephContext *cct;
+
+  XMLObj *alloc_obj(const char *el) override;
+public:
+  explicit RGWACLXMLParser_S3(CephContext *_cct) : cct(_cct) {}
+};
+
 XMLObj *RGWACLXMLParser_S3::alloc_obj(const char *el)
 {
   XMLObj * obj = NULL;
@@ -572,18 +544,97 @@ XMLObj *RGWACLXMLParser_S3::alloc_obj(const char *el)
   return obj;
 }
 
-ACLGroupTypeEnum ACLGrant_S3::uri_to_group(string& uri)
+namespace rgw::s3 {
+
+ACLGroupTypeEnum acl_uri_to_group(std::string_view uri)
 {
-  if (uri.compare(rgw_uri_all_users) == 0)
+  if (uri == rgw_uri_all_users)
     return ACL_GROUP_ALL_USERS;
-  else if (uri.compare(rgw_uri_auth_users) == 0)
+  else if (uri == rgw_uri_auth_users)
     return ACL_GROUP_AUTHENTICATED_USERS;
 
   return ACL_GROUP_NONE;
 }
 
+bool acl_group_to_uri(ACLGroupTypeEnum group, std::string& uri)
+{
+  switch (group) {
+  case ACL_GROUP_ALL_USERS:
+    uri = rgw_uri_all_users;
+    return true;
+  case ACL_GROUP_AUTHENTICATED_USERS:
+    uri = rgw_uri_auth_users;
+    return true;
+  default:
+    return false;
+  }
+}
 
-namespace rgw::s3 {
+int parse_policy(const DoutPrefixProvider* dpp, optional_yield y,
+                 rgw::sal::Driver* driver, std::string_view document,
+                 RGWAccessControlPolicy& policy, std::string& err_msg)
+{
+  RGWACLXMLParser_S3 parser(dpp->get_cct());
+  if (!parser.init()) {
+    return -EINVAL;
+  }
+  if (!parser.parse(document.data(), document.size(), 1)) {
+    return -EINVAL;
+  }
+
+  const auto xml_root = static_cast<RGWAccessControlPolicy_S3*>(
+      parser.find_first("AccessControlPolicy"));
+  if (!xml_root) {
+    err_msg = "Missing element AccessControlPolicy";
+    return -EINVAL;
+  }
+
+  const auto xml_owner = static_cast<ACLOwner_S3*>(
+      xml_root->find_first("Owner"));
+  if (!xml_owner) {
+    err_msg = "Missing element Owner";
+    return -EINVAL;
+  }
+
+  // owner must exist
+  std::unique_ptr<rgw::sal::User> user =
+      driver->get_user(rgw_user{xml_owner->id});
+  if (user->load_user(dpp, y) < 0) {
+    ldpp_dout(dpp, 10) << "acl owner does not exist" << dendl;
+    err_msg = "Invalid Owner ID";
+    return -EINVAL;
+  }
+
+  ACLOwner& owner = policy.get_owner();
+  owner.id = xml_owner->id;
+  if (!xml_owner->display_name.empty()) {
+    owner.display_name = xml_owner->display_name;
+  } else {
+    owner.display_name = user->get_display_name();
+  }
+
+  const auto xml_acl = static_cast<ACLOwner_S3*>(
+      xml_root->find_first("AccessControlList"));
+  if (!xml_acl) {
+    err_msg = "Missing element AccessControlList";
+    return -EINVAL;
+  }
+
+  // iterate parsed grants
+  XMLObjIter iter = xml_acl->find("Grant");
+  ACLGrant_S3* xml_grant = static_cast<ACLGrant_S3*>(iter.get_next());
+  while (xml_grant) {
+    ACLGrant grant;
+    int r = resolve_grant(dpp, y, driver, *xml_grant, grant, err_msg);
+    if (r < 0) {
+      return r;
+    }
+    policy.get_acl().add_grant(grant);
+    xml_grant = static_cast<ACLGrant_S3*>(iter.get_next());
+  }
+
+  return 0;
+}
 
 void write_policy_xml(const RGWAccessControlPolicy& policy,
                       std::ostream& out)
index 7b8489299715ca15965baa1b6371f59508538da4..2341461783fd4a1c05ba37903d8b0aa7d4e25f2f 100644 (file)
@@ -8,85 +8,24 @@
 #include <iosfwd>
 #include <include/types.h>
 
-#include "include/str_list.h"
+#include "common/async/yield_context.h"
 #include "rgw_xml.h"
 #include "rgw_acl.h"
 #include "rgw_sal_fwd.h"
 
-class RGWUserCtl;
-
-class ACLPermission_S3 : public ACLPermission, public XMLObj
-{
-public:
-  ACLPermission_S3() {}
-  virtual ~ACLPermission_S3() override {}
-
-  bool xml_end(const char *el) override;
-};
-
-class ACLGrantee_S3 : public XMLObj
-{
-public:
-  ACLGrantee_S3() {}
-  virtual ~ACLGrantee_S3() override {}
-
-  bool xml_start(const char *el, const char **attr);
-};
-
-
-class ACLGrant_S3 : public ACLGrant, public XMLObj
-{
-public:
-  ACLGrant_S3() {}
-  virtual ~ACLGrant_S3() override {}
-
-  bool xml_end(const char *el) override;
-  bool xml_start(const char *el, const char **attr);
-
-  static ACLGroupTypeEnum uri_to_group(std::string& uri);
-  static bool group_to_uri(ACLGroupTypeEnum group, std::string& uri);
-};
-
-class RGWAccessControlList_S3 : public RGWAccessControlList, public XMLObj
-{
-public:
-  bool xml_end(const char *el) override;
-};
-
-class ACLOwner_S3 : public ACLOwner, public XMLObj
-{
-public:
-  ACLOwner_S3() {}
-  virtual ~ACLOwner_S3() override {}
-
-  bool xml_end(const char *el) override;
-};
-
 class RGWEnv;
 
-class RGWAccessControlPolicy_S3 : public RGWAccessControlPolicy, public XMLObj
-{
-public:
-  bool xml_end(const char *el) override;
-
-  int rebuild(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver, ACLOwner *owner,
-             RGWAccessControlPolicy& dest, std::string &err_msg);
-};
-
-/**
- * Interfaces with the webserver's XML handling code
- * to parse it in a way that makes sense for the rgw.
- */
-class RGWACLXMLParser_S3 : public RGWXMLParser
-{
-  CephContext *cct;
+namespace rgw::s3 {
 
-  XMLObj *alloc_obj(const char *el) override;
-public:
-  explicit RGWACLXMLParser_S3(CephContext *_cct) : cct(_cct) {}
-};
+ACLGroupTypeEnum acl_uri_to_group(std::string_view uri);
+bool acl_group_to_uri(ACLGroupTypeEnum group, std::string& uri);
 
-namespace rgw::s3 {
+/// Construct a policy from an AccessControlPolicy xml document. Email grantees
+/// are looked up and converted to a corresponding CanonicalUser grant. All user
+/// ids are verified to exist.
+int parse_policy(const DoutPrefixProvider* dpp, optional_yield y,
+                 rgw::sal::Driver* driver, std::string_view document,
+                 RGWAccessControlPolicy& policy, std::string& err_msg);
 
 /// Write an AccessControlPolicy xml document for the given policy.
 void write_policy_xml(const RGWAccessControlPolicy& policy,
index f822c13932dfa3283397b43c57691d822287518e..8a0d19526ad56e698f482bee47186e296f88a1c9 100644 (file)
@@ -512,7 +512,7 @@ int rgw_build_bucket_policies(const DoutPrefixProvider *dpp, rgw::sal::Driver* d
   }
 
   if(s->dialect.compare("s3") == 0) {
-    s->bucket_acl = std::make_unique<RGWAccessControlPolicy_S3>();
+    s->bucket_acl = std::make_unique<RGWAccessControlPolicy>();
   } else if(s->dialect.compare("swift")  == 0) {
     /* We aren't allocating the account policy for those operations using
      * the Swift's infrastructure that don't really need req_state::user.
@@ -5982,25 +5982,10 @@ void RGWDeleteLC::pre_exec()
 
 void RGWPutACLs::execute(optional_yield y)
 {
-  bufferlist bl;
-
-  RGWAccessControlPolicy_S3 *policy = NULL;
-  RGWACLXMLParser_S3 parser(s->cct);
-  RGWAccessControlPolicy_S3 new_policy;
-  stringstream ss;
-
-  op_ret = 0; /* XXX redundant? */
-
-  if (!parser.init()) {
-    op_ret = -EINVAL;
-    return;
-  }
-
-
   RGWAccessControlPolicy* const existing_policy = \
     (rgw::sal::Object::empty(s->object.get()) ? s->bucket_acl.get() : s->object_acl.get());
 
-  owner = existing_policy->get_owner();
+  const ACLOwner& existing_owner = existing_policy->get_owner();
 
   op_ret = get_params(y);
   if (op_ret < 0) {
@@ -6023,26 +6008,24 @@ void RGWPutACLs::execute(optional_yield y)
     return;
   }
 
+  RGWAccessControlPolicy new_policy;
   if (!s->canned_acl.empty() || s->has_acl_header) {
-    op_ret = get_policy_from_state(driver, s, ss);
-    if (op_ret < 0)
-      return;
-
-    data.clear();
-    data.append(ss.str());
+    op_ret = get_policy_from_state(existing_owner, new_policy);
+  } else {
+    op_ret = rgw::s3::parse_policy(this, y, driver, {data.c_str(), data.length()},
+                                   new_policy, s->err.message);
   }
-
-  if (!parser.parse(data.c_str(), data.length(), 1)) {
-    op_ret = -EINVAL;
+  if (op_ret < 0)
     return;
-  }
-  policy = static_cast<RGWAccessControlPolicy_S3 *>(parser.find_first("AccessControlPolicy"));
-  if (!policy) {
-    op_ret = -EINVAL;
+
+  if (!existing_owner.id.empty() &&
+      existing_owner.id != new_policy.get_owner().id) {
+    s->err.message = "Cannot modify ACL Owner";
+    op_ret = -EPERM;
     return;
   }
 
-  const RGWAccessControlList& req_acl = policy->get_acl();
+  const RGWAccessControlList& req_acl = new_policy.get_acl();
   const multimap<string, ACLGrant>& req_grant_map = req_acl.get_grant_map();
 #define ACL_GRANTS_MAX_NUM      100
   int max_num = s->cct->_conf->rgw_acl_grants_max_num;
@@ -6063,13 +6046,8 @@ void RGWPutACLs::execute(optional_yield y)
 
   // forward bucket acl requests to meta master zone
   if ((rgw::sal::Object::empty(s->object.get()))) {
-    bufferlist in_data;
-    // include acl data unless it was generated from a canned_acl
-    if (s->canned_acl.empty()) {
-      in_data.append(data);
-    }
     op_ret = rgw_forward_request_to_master(this, *s->penv.site, s->user->get_id(),
-                                           &in_data, nullptr, s->info, y);
+                                           &data, nullptr, s->info, y);
     if (op_ret < 0) {
       ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
       return;
@@ -6078,15 +6056,9 @@ void RGWPutACLs::execute(optional_yield y)
 
   if (s->cct->_conf->subsys.should_gather<ceph_subsys_rgw, 15>()) {
     ldpp_dout(this, 15) << "Old AccessControlPolicy";
-    rgw::s3::write_policy_xml(*policy, *_dout);
+    rgw::s3::write_policy_xml(*existing_policy, *_dout);
     *_dout << dendl;
-  }
-
-  op_ret = policy->rebuild(this, driver, &owner, new_policy, s->err.message);
-  if (op_ret < 0)
-    return;
 
-  if (s->cct->_conf->subsys.should_gather<ceph_subsys_rgw, 15>()) {
     ldpp_dout(this, 15) << "New AccessControlPolicy:";
     rgw::s3::write_policy_xml(new_policy, *_dout);
     *_dout << dendl;
@@ -6098,6 +6070,8 @@ void RGWPutACLs::execute(optional_yield y)
     op_ret = -EACCES;
     return;
   }
+
+  bufferlist bl;
   new_policy.encode(bl);
   map<string, bufferlist> attrs;
 
index 70266cbfc6673afe70b5f325346e8568fce36e61..948b68f54d8431533ab02d1c7738e3e2feaf7058 100644 (file)
@@ -1576,7 +1576,6 @@ public:
 class RGWPutACLs : public RGWOp {
 protected:
   bufferlist data;
-  ACLOwner owner;
 
 public:
   RGWPutACLs() {}
@@ -1586,7 +1585,8 @@ public:
   void pre_exec() override;
   void execute(optional_yield y) override;
 
-  virtual int get_policy_from_state(rgw::sal::Driver* driver, req_state *s, std::stringstream& ss) { return 0; }
+  virtual int get_policy_from_state(const ACLOwner& owner,
+                                    RGWAccessControlPolicy& p) { return 0; }
   virtual int get_params(optional_yield y) = 0;
   void send_response() override = 0;
   const char* name() const override { return "put_acls"; }
@@ -1636,7 +1636,6 @@ public:
   void pre_exec() override;
   void execute(optional_yield y) override;
 
-//  virtual int get_policy_from_state(RGWRados* driver, req_state *s, std::stringstream& ss) { return 0; }
   virtual int get_params(optional_yield y) = 0;
   void send_response() override = 0;
   const char* name() const override { return "put_lifecycle"; }
index 73f16e449e9943b991009df6cd04f6ca1b6b6e91..ed8e1afa7b7714e2f65ee9bf54f786ac1798731a 100644 (file)
@@ -2383,7 +2383,7 @@ void RGWStatBucket_ObjStore_S3::send_response()
 }
 
 static int create_s3_policy(req_state *s, rgw::sal::Driver* driver,
-                           RGWAccessControlPolicy_S3& s3policy,
+                           RGWAccessControlPolicypolicy,
                            const ACLOwner& owner)
 {
   if (s->has_acl_header) {
@@ -2391,11 +2391,11 @@ static int create_s3_policy(req_state *s, rgw::sal::Driver* driver,
       return -ERR_INVALID_REQUEST;
 
     return rgw::s3::create_policy_from_headers(s, driver, owner,
-                                               *s->info.env, s3policy);
+                                               *s->info.env, policy);
   }
 
   return rgw::s3::create_canned_acl(owner, s->bucket_owner,
-                                    s->canned_acl, s3policy);
+                                    s->canned_acl, policy);
 }
 
 class RGWLocationConstraint : public XMLObj
@@ -2449,7 +2449,6 @@ public:
 
 int RGWCreateBucket_ObjStore_S3::get_params(optional_yield y)
 {
-  RGWAccessControlPolicy_S3 s3policy;
   bool relaxed_names = s->cct->_conf->rgw_relaxed_s3_bucket_names;
 
   int r;
@@ -2458,12 +2457,10 @@ int RGWCreateBucket_ObjStore_S3::get_params(optional_yield y)
     if (r) return r;
   }
 
-  r = create_s3_policy(s, driver, s3policy, s->owner);
+  r = create_s3_policy(s, driver, policy, s->owner);
   if (r < 0)
     return r;
 
-  policy = s3policy;
-
   const auto max_size = s->cct->_conf->rgw_max_put_param_size;
 
   int op_ret = 0;
@@ -2591,13 +2588,10 @@ int RGWPutObj_ObjStore_S3::get_params(optional_yield y)
     return ret;
   }
 
-  RGWAccessControlPolicy_S3 s3policy;
-  ret = create_s3_policy(s, driver, s3policy, s->owner);
+  ret = create_s3_policy(s, driver, policy, s->owner);
   if (ret < 0)
     return ret;
 
-  policy = s3policy;
-
   if_match = s->info.env->get("HTTP_IF_MATCH");
   if_nomatch = s->info.env->get("HTTP_IF_NONE_MATCH");
 
@@ -3451,16 +3445,8 @@ void RGWDeleteObj_ObjStore_S3::send_response()
 
 int RGWCopyObj_ObjStore_S3::init_dest_policy()
 {
-  RGWAccessControlPolicy_S3 s3policy;
-
   /* build a policy for the target object */
-  int r = create_s3_policy(s, driver, s3policy, s->owner);
-  if (r < 0)
-    return r;
-
-  dest_policy = s3policy;
-
-  return 0;
+  return create_s3_policy(s, driver, dest_policy, s->owner);
 }
 
 int RGWCopyObj_ObjStore_S3::get_params(optional_yield y)
@@ -3622,25 +3608,16 @@ int RGWPutACLs_ObjStore_S3::get_params(optional_yield y)
   return ret;
 }
 
-int RGWPutACLs_ObjStore_S3::get_policy_from_state(rgw::sal::Driver* driver,
-                                                 req_state *s,
-                                                 stringstream& ss)
+int RGWPutACLs_ObjStore_S3::get_policy_from_state(const ACLOwner& owner,
+                                                  RGWAccessControlPolicy& policy)
 {
-  RGWAccessControlPolicy_S3 s3policy;
-
   // bucket-* canned acls do not apply to bucket
   if (rgw::sal::Object::empty(s->object.get())) {
     if (s->canned_acl.find("bucket") != string::npos)
       s->canned_acl.clear();
   }
 
-  int r = create_s3_policy(s, driver, s3policy, owner);
-  if (r < 0)
-    return r;
-
-  rgw::s3::write_policy_xml(s3policy, ss);
-
-  return 0;
+  return create_s3_policy(s, driver, policy, owner);
 }
 
 void RGWPutACLs_ObjStore_S3::send_response()
@@ -3973,14 +3950,7 @@ int RGWInitMultipart_ObjStore_S3::get_params(optional_yield y)
     return ret;
   }
 
-  RGWAccessControlPolicy_S3 s3policy;
-  ret = create_s3_policy(s, driver, s3policy, s->owner);
-  if (ret < 0)
-    return ret;
-
-  policy = s3policy;
-
-  return 0;
+  return create_s3_policy(s, driver, policy, s->owner);
 }
 
 void RGWInitMultipart_ObjStore_S3::send_response()
index c73971a5fe6756f039da1bf3ee28ecf003305d93..d15ddaba35aebefda48c26ab229c322460ea09c5 100644 (file)
@@ -355,7 +355,8 @@ public:
   RGWPutACLs_ObjStore_S3() {}
   ~RGWPutACLs_ObjStore_S3() override {}
 
-  int get_policy_from_state(rgw::sal::Driver* driver, req_state *s, std::stringstream& ss) override;
+  int get_policy_from_state(const ACLOwner& owner,
+                            RGWAccessControlPolicy& p) override;
   void send_response() override;
   int get_params(optional_yield y) override;
 };