]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: swift: ability to update swift read and write acls separately. 14499/head
authorMarcus Watts <mwatts@redhat.com>
Thu, 13 Apr 2017 08:13:31 +0000 (04:13 -0400)
committerMarcus Watts <mwatts@redhat.com>
Fri, 21 Apr 2017 22:24:37 +0000 (18:24 -0400)
openstack swift stores read and write acls as separate attributes
which can be updated independently.  Ceph stores acls in one merged
structure.  To emulate swift behavior, when updating an acl, take
the old acl and merge the unmodified bits into the replacement acl.

Fixes: http://tracker.ceph.com/issues/19289
Signed-off-by: Marcus Watts <mwatts@redhat.com>
src/rgw/rgw_acl_swift.cc
src/rgw/rgw_acl_swift.h
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest_swift.cc

index 78b60124ba64b3de9943d53447bf059e4e22e8aa..339b93bbe063bc59dcdb0089f6168a43591b3686 100644 (file)
@@ -179,11 +179,13 @@ int RGWAccessControlPolicy_SWIFT::create(RGWRados* const store,
                                          const rgw_user& id,
                                          const std::string& name,
                                          const std::string& read_list,
-                                         const std::string& write_list)
+                                         const std::string& write_list,
+                                         uint32_t& rw_mask)
 {
   acl.create_default(id, name);
   owner.set_id(id);
   owner.set_name(name);
+  rw_mask = 0;
 
   if (read_list.size()) {
     std::vector<std::string> uids;
@@ -200,6 +202,7 @@ int RGWAccessControlPolicy_SWIFT::create(RGWRados* const store,
                     << r << dendl;
       return r;
     }
+    rw_mask |= SWIFT_PERM_READ;
   }
   if (write_list.size()) {
     std::vector<std::string> uids;
@@ -216,10 +219,45 @@ int RGWAccessControlPolicy_SWIFT::create(RGWRados* const store,
                     << r << dendl;
       return r;
     }
+    rw_mask |= SWIFT_PERM_WRITE;
   }
   return 0;
 }
 
+void RGWAccessControlPolicy_SWIFT::filter_merge(uint32_t rw_mask,
+                                                RGWAccessControlPolicy_SWIFT *old)
+{
+  /* rw_mask&SWIFT_PERM_READ => setting read acl,
+   * rw_mask&SWIFT_PERM_WRITE => setting write acl
+   * when bit is cleared, copy matching elements from old.
+   */
+  if (rw_mask == (SWIFT_PERM_READ|SWIFT_PERM_WRITE)) {
+    return;
+  }
+  rw_mask ^= (SWIFT_PERM_READ|SWIFT_PERM_WRITE);
+  for (auto &iter: old->acl.get_grant_map()) {
+    ACLGrant& grant = iter.second;
+    uint32_t perm = grant.get_permission().get_permissions();
+    rgw_user id;
+    string url_spec;
+    if (!grant.get_id(id)) {
+      if (grant.get_group() != ACL_GROUP_ALL_USERS) {
+        url_spec = grant.get_referer();
+        if (url_spec.empty()) {
+          continue;
+        }
+        if (perm == 0) {
+          /* We need to carry also negative, HTTP referrer-based ACLs. */
+          perm = SWIFT_PERM_READ;
+        }
+      }
+    }
+    if (perm & rw_mask) {
+      acl.add_grant(&grant);
+    }
+  }
+}
+
 void RGWAccessControlPolicy_SWIFT::to_str(string& read, string& write)
 {
   multimap<string, ACLGrant>& m = acl.get_grant_map();
index b74a85ecfe19486153727e4418ab32693fc28946..883b623af182a1bc2e7ff1daa668dbcd6a00208a 100644 (file)
@@ -27,7 +27,9 @@ public:
              const rgw_user& id,
              const std::string& name,
              const std::string& read_list,
-             const std::string& write_list);
+             const std::string& write_list,
+             uint32_t& rw_mask);
+  void filter_merge(uint32_t mask, RGWAccessControlPolicy_SWIFT *policy);
   void to_str(std::string& read, std::string& write);
 };
 
index a000aaffc41a7b9835a960aaf77bf48651768f41..ff60aa6572d9bb4359c8a338db70b1fd79729409 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "compressor/Compressor.h"
 
+#include "rgw_acl_swift.h"
 
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_rgw
@@ -3543,6 +3544,12 @@ void RGWPutMetadataBucket::execute()
    * the hood. This method will add the new items only if the map doesn't
    * contain such keys yet. */
   if (has_policy) {
+    if (s->dialect.compare("swift") == 0) {
+       auto old_policy = static_cast<RGWAccessControlPolicy_SWIFT*>(s->bucket_acl);
+       auto new_policy = static_cast<RGWAccessControlPolicy_SWIFT*>(&policy);
+       new_policy->filter_merge(policy_rw_mask, old_policy);
+       policy = *new_policy;
+    }
     buffer::list bl;
     policy.encode(bl);
     emplace_attr(RGW_ATTR_ACL, std::move(bl));
index 9bda710dc59c2d29431d452b2c7def744198d9e7..3e6997facb91fd537b5e1d9024335f9b2364963b 100644 (file)
@@ -940,6 +940,7 @@ protected:
   map<string, buffer::list> attrs;
   set<string> rmattr_names;
   bool has_policy, has_cors;
+  uint32_t policy_rw_mask;
   RGWAccessControlPolicy policy;
   RGWCORSConfiguration cors_config;
   string placement_rule;
@@ -947,7 +948,7 @@ protected:
 
 public:
   RGWPutMetadataBucket()
-    : has_policy(false), has_cors(false)
+    : has_policy(false), has_cors(false), policy_rw_mask(0)
   {}
 
   void emplace_attr(std::string&& key, buffer::list&& bl) {
index 40c940b47bfb560903a2696632652ef82d208631..7a447c0f798c2b5c13defd4daad6565c5f61abc8 100644 (file)
@@ -502,6 +502,7 @@ static int get_swift_container_settings(req_state * const s,
                                         RGWRados * const store,
                                         RGWAccessControlPolicy * const policy,
                                         bool * const has_policy,
+                                        uint32_t * rw_mask,
                                         RGWCORSConfiguration * const cors_config,
                                         bool * const has_cors)
 {
@@ -524,7 +525,8 @@ static int get_swift_container_settings(req_state * const s,
                                        s->user->user_id,
                                        s->user->display_name,
                                        read_list,
-                                       write_list);
+                                       write_list,
+                                       *rw_mask);
     if (r < 0) {
       return r;
     }
@@ -622,8 +624,10 @@ static int get_swift_versioning_settings(
 int RGWCreateBucket_ObjStore_SWIFT::get_params()
 {
   bool has_policy;
+  uint32_t policy_rw_mask = 0;
 
-  int r = get_swift_container_settings(s, store, &policy, &has_policy, &cors_config, &has_cors);
+  int r = get_swift_container_settings(s, store, &policy, &has_policy,
+                                      &policy_rw_mask, &cors_config, &has_cors);
   if (r < 0) {
     return r;
   }
@@ -891,7 +895,7 @@ int RGWPutMetadataBucket_ObjStore_SWIFT::get_params()
   }
 
   int r = get_swift_container_settings(s, store, &policy, &has_policy,
-                                      &cors_config, &has_cors);
+                                      &policy_rw_mask, &cors_config, &has_cors);
   if (r < 0) {
     return r;
   }