X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Frgw%2Frgw_acl_swift.cc;fp=src%2Fceph%2Fsrc%2Frgw%2Frgw_acl_swift.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=71f32a69528fb3921669a0085c1f47160111c9b2;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/rgw/rgw_acl_swift.cc b/src/ceph/src/rgw/rgw_acl_swift.cc deleted file mode 100644 index 71f32a6..0000000 --- a/src/ceph/src/rgw/rgw_acl_swift.cc +++ /dev/null @@ -1,431 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include - -#include - -#include - -#include "common/ceph_json.h" -#include "rgw_common.h" -#include "rgw_user.h" -#include "rgw_acl_swift.h" - -#define dout_subsys ceph_subsys_rgw - -using namespace std; - -#define SWIFT_PERM_READ RGW_PERM_READ_OBJS -#define SWIFT_PERM_WRITE RGW_PERM_WRITE_OBJS -/* FIXME: do we really need separate RW? */ -#define SWIFT_PERM_RWRT (SWIFT_PERM_READ | SWIFT_PERM_WRITE) -#define SWIFT_PERM_ADMIN RGW_PERM_FULL_CONTROL - -#define SWIFT_GROUP_ALL_USERS ".r:*" - -static int parse_list(const std::string& uid_list, - std::vector& uids) /* out */ -{ - char *s = strdup(uid_list.c_str()); - if (!s) { - return -ENOMEM; - } - - char *tokctx; - const char *p = strtok_r(s, " ,", &tokctx); - while (p) { - if (*p) { - string acl = p; - uids.push_back(acl); - } - p = strtok_r(NULL, " ,", &tokctx); - } - free(s); - return 0; -} - -static bool is_referrer(const std::string& designator) -{ - return designator.compare(".r") == 0 || - designator.compare(".ref") == 0 || - designator.compare(".referer") == 0 || - designator.compare(".referrer") == 0; -} - -static bool uid_is_public(const string& uid) -{ - if (uid[0] != '.' || uid[1] != 'r') - return false; - - int pos = uid.find(':'); - if (pos < 0 || pos == (int)uid.size()) - return false; - - string sub = uid.substr(0, pos); - string after = uid.substr(pos + 1); - - if (after.compare("*") != 0) - return false; - - return is_referrer(sub); -} - -static boost::optional referrer_to_grant(std::string url_spec, - const uint32_t perm) -{ - /* This function takes url_spec as non-ref std::string because of the trim - * operation that is essential to preserve compliance with Swift. It can't - * be easily accomplished with boost::string_ref. */ - try { - bool is_negative; - ACLGrant grant; - - if ('-' == url_spec[0]) { - url_spec = url_spec.substr(1); - boost::algorithm::trim(url_spec); - - is_negative = true; - } else { - is_negative = false; - } - - if (url_spec != RGW_REFERER_WILDCARD) { - if ('*' == url_spec[0]) { - url_spec = url_spec.substr(1); - boost::algorithm::trim(url_spec); - } - - if (url_spec.empty() || url_spec == ".") { - return boost::none; - } - } else { - /* Please be aware we're specially handling the .r:* in _add_grant() - * of RGWAccessControlList as the S3 API has a similar concept, and - * thus we can have a small portion of compatibility. */ - } - - grant.set_referer(url_spec, is_negative ? 0 : perm); - return grant; - } catch (std::out_of_range) { - return boost::none; - } -} - -static ACLGrant user_to_grant(CephContext* const cct, - RGWRados* const store, - const std::string& uid, - const uint32_t perm) -{ - rgw_user user(uid); - RGWUserInfo grant_user; - ACLGrant grant; - - if (rgw_get_user_info_by_uid(store, user, grant_user) < 0) { - ldout(cct, 10) << "grant user does not exist: " << uid << dendl; - /* skipping silently */ - grant.set_canon(user, std::string(), perm); - } else { - grant.set_canon(user, grant_user.display_name, perm); - } - - return grant; -} - -int RGWAccessControlPolicy_SWIFT::add_grants(RGWRados* const store, - const std::vector& uids, - const uint32_t perm) -{ - for (const auto& uid : uids) { - boost::optional grant; - ldout(cct, 20) << "trying to add grant for ACL uid=" << uid << dendl; - - /* Let's check whether the item has a separator potentially indicating - * a special meaning (like an HTTP referral-based grant). */ - const size_t pos = uid.find(':'); - if (std::string::npos == pos) { - /* No, it don't have -- we've got just a regular user identifier. */ - grant = user_to_grant(cct, store, uid, perm); - } else { - /* Yes, *potentially* an HTTP referral. */ - auto designator = uid.substr(0, pos); - auto designatee = uid.substr(pos + 1); - - /* Swift strips whitespaces at both beginning and end. */ - boost::algorithm::trim(designator); - boost::algorithm::trim(designatee); - - if (! boost::algorithm::starts_with(designator, ".")) { - grant = user_to_grant(cct, store, uid, perm); - } else if ((perm & SWIFT_PERM_WRITE) == 0 && is_referrer(designator)) { - /* HTTP referrer-based ACLs aren't acceptable for writes. */ - grant = referrer_to_grant(designatee, perm); - } - } - - if (grant) { - acl.add_grant(&*grant); - } else { - return -EINVAL; - } - } - - return 0; -} - - -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, - 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; - int r = parse_list(read_list, uids); - if (r < 0) { - ldout(cct, 0) << "ERROR: parse_list for read returned r=" - << r << dendl; - return r; - } - - r = add_grants(store, uids, SWIFT_PERM_READ); - if (r < 0) { - ldout(cct, 0) << "ERROR: add_grants for read returned r=" - << r << dendl; - return r; - } - rw_mask |= SWIFT_PERM_READ; - } - if (write_list.size()) { - std::vector uids; - int r = parse_list(write_list, uids); - if (r < 0) { - ldout(cct, 0) << "ERROR: parse_list for write returned r=" - << r << dendl; - return r; - } - - r = add_grants(store, uids, SWIFT_PERM_WRITE); - if (r < 0) { - ldout(cct, 0) << "ERROR: add_grants for write returned r=" - << 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(); - multimap::iterator iter; - - for (iter = m.begin(); iter != m.end(); ++iter) { - ACLGrant& grant = iter->second; - const 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) { - id = SWIFT_GROUP_ALL_USERS; - } else { - url_spec = grant.get_referer(); - if (url_spec.empty()) { - continue; - } - id = (perm != 0) ? ".r:" + url_spec : ".r:-" + url_spec; - } - } - if (perm & SWIFT_PERM_READ) { - if (!read.empty()) { - read.append(","); - } - read.append(id.to_str()); - } else if (perm & SWIFT_PERM_WRITE) { - if (!write.empty()) { - write.append(","); - } - write.append(id.to_str()); - } else if (perm == 0 && !url_spec.empty()) { - /* only X-Container-Read headers support referers */ - if (!read.empty()) { - read.append(","); - } - read.append(id.to_str()); - } - } -} - -void RGWAccessControlPolicy_SWIFTAcct::add_grants(RGWRados * const store, - const std::vector& uids, - const uint32_t perm) -{ - for (const auto& uid : uids) { - ACLGrant grant; - RGWUserInfo grant_user; - - if (uid_is_public(uid)) { - grant.set_group(ACL_GROUP_ALL_USERS, perm); - acl.add_grant(&grant); - } else { - rgw_user user(uid); - - if (rgw_get_user_info_by_uid(store, user, grant_user) < 0) { - ldout(cct, 10) << "grant user does not exist:" << uid << dendl; - /* skipping silently */ - grant.set_canon(user, std::string(), perm); - acl.add_grant(&grant); - } else { - grant.set_canon(user, grant_user.display_name, perm); - acl.add_grant(&grant); - } - } - } -} - -bool RGWAccessControlPolicy_SWIFTAcct::create(RGWRados * const store, - const rgw_user& id, - const std::string& name, - const std::string& acl_str) -{ - acl.create_default(id, name); - owner.set_id(id); - owner.set_name(name); - - JSONParser parser; - - if (!parser.parse(acl_str.c_str(), acl_str.length())) { - ldout(cct, 0) << "ERROR: JSONParser::parse returned error=" << dendl; - return false; - } - - JSONObjIter iter = parser.find_first("admin"); - if (!iter.end() && (*iter)->is_array()) { - std::vector admin; - decode_json_obj(admin, *iter); - ldout(cct, 0) << "admins: " << admin << dendl; - - add_grants(store, admin, SWIFT_PERM_ADMIN); - } - - iter = parser.find_first("read-write"); - if (!iter.end() && (*iter)->is_array()) { - std::vector readwrite; - decode_json_obj(readwrite, *iter); - ldout(cct, 0) << "read-write: " << readwrite << dendl; - - add_grants(store, readwrite, SWIFT_PERM_RWRT); - } - - iter = parser.find_first("read-only"); - if (!iter.end() && (*iter)->is_array()) { - std::vector readonly; - decode_json_obj(readonly, *iter); - ldout(cct, 0) << "read-only: " << readonly << dendl; - - add_grants(store, readonly, SWIFT_PERM_READ); - } - - return true; -} - -boost::optional RGWAccessControlPolicy_SWIFTAcct::to_str() const -{ - std::vector admin; - std::vector readwrite; - std::vector readonly; - - /* Parition the grant map into three not-overlapping groups. */ - for (const auto& item : get_acl().get_grant_map()) { - const ACLGrant& grant = item.second; - const uint32_t perm = grant.get_permission().get_permissions(); - - rgw_user id; - if (!grant.get_id(id)) { - if (grant.get_group() != ACL_GROUP_ALL_USERS) { - continue; - } - id = SWIFT_GROUP_ALL_USERS; - } else if (owner.get_id() == id) { - continue; - } - - if (SWIFT_PERM_ADMIN == (perm & SWIFT_PERM_ADMIN)) { - admin.insert(admin.end(), id.to_str()); - } else if (SWIFT_PERM_RWRT == (perm & SWIFT_PERM_RWRT)) { - readwrite.insert(readwrite.end(), id.to_str()); - } else if (SWIFT_PERM_READ == (perm & SWIFT_PERM_READ)) { - readonly.insert(readonly.end(), id.to_str()); - } else { - // FIXME: print a warning - } - } - - /* If there is no grant to serialize, let's exit earlier to not return - * an empty JSON object which brakes the functional tests of Swift. */ - if (admin.empty() && readwrite.empty() && readonly.empty()) { - return boost::none; - } - - /* Serialize the groups. */ - JSONFormatter formatter; - - formatter.open_object_section("acl"); - if (!readonly.empty()) { - encode_json("read-only", readonly, &formatter); - } - if (!readwrite.empty()) { - encode_json("read-write", readwrite, &formatter); - } - if (!admin.empty()) { - encode_json("admin", admin, &formatter); - } - formatter.close_section(); - - std::ostringstream oss; - formatter.flush(oss); - - return oss.str(); -}