From: Marcus Watts Date: Thu, 13 Apr 2017 08:13:31 +0000 (-0400) Subject: rgw: swift: ability to update swift read and write acls separately. X-Git-Tag: v12.0.3~221^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=93c705db2f9b92ff634886f7740178055247890d;p=ceph.git rgw: swift: ability to update swift read and write acls separately. 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 --- diff --git a/src/rgw/rgw_acl_swift.cc b/src/rgw/rgw_acl_swift.cc index 78b60124ba64..339b93bbe063 100644 --- a/src/rgw/rgw_acl_swift.cc +++ b/src/rgw/rgw_acl_swift.cc @@ -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 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 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& m = acl.get_grant_map(); diff --git a/src/rgw/rgw_acl_swift.h b/src/rgw/rgw_acl_swift.h index b74a85ecfe19..883b623af182 100644 --- a/src/rgw/rgw_acl_swift.h +++ b/src/rgw/rgw_acl_swift.h @@ -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); }; diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index a000aaffc41a..ff60aa6572d9 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -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(s->bucket_acl); + auto new_policy = static_cast(&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)); diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 9bda710dc59c..3e6997facb91 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -940,6 +940,7 @@ protected: map attrs; set 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) { diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 40c940b47bfb..7a447c0f798c 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -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; }