From: Yehuda Sadeh Date: Tue, 11 Jun 2013 04:59:15 +0000 (-0700) Subject: rgw: pass grant headers to target when writeing object X-Git-Tag: v0.67-rc1~128^2~25^2~38 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ea3efca3fd161d9ed56df3c28f558ce593aae470;p=ceph.git rgw: pass grant headers to target when writeing object When writing object to remote gateway. Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index f571de0f7315..86618bd674b2 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -158,29 +158,6 @@ static void rgw_get_request_metadata(CephContext *cct, struct req_info& info, ma } } -static int policy_from_attrset(CephContext *cct, map& attrset, RGWAccessControlPolicy *policy) -{ - map::iterator aiter = attrset.find(RGW_ATTR_ACL); - if (aiter == attrset.end()) - return -EIO; - - bufferlist& bl = aiter->second; - bufferlist::iterator iter = bl.begin(); - try { - policy->decode(iter); - } catch (buffer::error& err) { - ldout(cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl; - return -EIO; - } - if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 15)) { - RGWAccessControlPolicy_S3 *s3policy = static_cast(policy); - ldout(cct, 15) << "Read AccessControlPolicy"; - s3policy->to_xml(*_dout); - *_dout << dendl; - } - return 0; -} - /** * Get the AccessControlPolicy for an object off of disk. * policy: must point to a valid RGWACL, and will be filled upon return. @@ -416,7 +393,7 @@ int RGWGetObj::read_user_manifest_part(rgw_bucket& bucket, RGWObjEnt& ent, RGWAc goto done_err; } - ret = policy_from_attrset(s->cct, attrs, &obj_policy); + ret = rgw_policy_from_attrset(s->cct, attrs, &obj_policy); if (ret < 0) goto done_err; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 0583ba014bcf..a9a4815036a0 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -11,6 +11,7 @@ #include "rgw_rados.h" #include "rgw_cache.h" #include "rgw_acl.h" +#include "rgw_acl_s3.h" /* for dumping s3policy in debug log */ #include "rgw_metadata.h" #include "rgw_bucket.h" @@ -1264,6 +1265,29 @@ int RGWRados::decode_policy(bufferlist& bl, ACLOwner *owner) return 0; } +int rgw_policy_from_attrset(CephContext *cct, map& attrset, RGWAccessControlPolicy *policy) +{ + map::iterator aiter = attrset.find(RGW_ATTR_ACL); + if (aiter == attrset.end()) + return -EIO; + + bufferlist& bl = aiter->second; + bufferlist::iterator iter = bl.begin(); + try { + policy->decode(iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl; + return -EIO; + } + if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 15)) { + RGWAccessControlPolicy_S3 *s3policy = static_cast(policy); + ldout(cct, 15) << "Read AccessControlPolicy"; + s3policy->to_xml(*_dout); + *_dout << dendl; + } + return 0; +} + /** * get listing of the objects in a bucket. * bucket: bucket to list contents of diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index d68978237945..cee93e913c06 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -44,6 +44,8 @@ static inline void get_obj_bucket_and_oid_key(rgw_obj& obj, rgw_bucket& bucket, prepend_bucket_marker(bucket, obj.key, key); } +int rgw_policy_from_attrset(CephContext *cct, map& attrset, RGWAccessControlPolicy *policy); + struct RGWUsageBatch { map m; diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc index c7e11a958417..e3e1c0ba7f8c 100644 --- a/src/rgw/rgw_rest_client.cc +++ b/src/rgw/rgw_rest_client.cc @@ -284,6 +284,76 @@ int RGWRESTStreamRequest::add_output_data(bufferlist& bl) return process_request(handle, false, &done); } +static void grants_by_type_add_one_grant(map& grants_by_type, int perm, ACLGrant& grant) +{ + string& s = grants_by_type[perm]; + + if (!s.empty()) + s.append(", "); + + string id_type_str; + ACLGranteeType& type = grant.get_type(); + switch (type.get_type()) { + case ACL_TYPE_GROUP: + id_type_str = "uri"; + break; + case ACL_TYPE_EMAIL_USER: + id_type_str = "emailAddress"; + break; + default: + id_type_str = "id"; + } + string id; + grant.get_id(id); + s.append(id_type_str + "=\"" + id + "\""); +} + +struct grant_type_to_header { + int type; + const char *header; +}; + +struct grant_type_to_header grants_headers_def[] = { + { RGW_PERM_FULL_CONTROL, "x-amz-grant-full-control"}, + { RGW_PERM_READ, "x-amz-grant-read"}, + { RGW_PERM_WRITE, "x-amz-grant-write"}, + { RGW_PERM_READ_ACP, "x-amz-grant-read-acp"}, + { RGW_PERM_WRITE_ACP, "x-amz-grant-write-acp"}, + { 0, NULL} +}; + +static bool grants_by_type_check_perm(map& grants_by_type, int perm, ACLGrant& grant, int check_perm) +{ + if ((perm & check_perm) == perm) { + grants_by_type_add_one_grant(grants_by_type, check_perm, grant); + return true; + } + return false; +} + +static void grants_by_type_add_perm(map& grants_by_type, int perm, ACLGrant& grant) +{ + struct grant_type_to_header *t; + + for (t = grants_headers_def; t->header; t++) { + if (grants_by_type_check_perm(grants_by_type, perm, grant, t->type)) + return; + } +} + +static void add_grants_headers(map& grants, map& attrs, map& meta_map) +{ + struct grant_type_to_header *t; + + for (t = grants_headers_def; t->header; t++) { + map::iterator iter = grants.find(t->type); + if (iter != grants.end()) { + attrs[t->header] = iter->second; + meta_map[t->header] = iter->second; + } + } +} + int RGWRESTStreamRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uint64_t obj_size, map& attrs) { string resource = obj.bucket.name + "/" + obj.object; @@ -311,12 +381,6 @@ int RGWRESTStreamRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uint64_t new_info.script_uri.append(resource); new_info.request_uri = new_info.script_uri; - int ret = sign_request(key, new_env, new_info); - if (ret < 0) { - ldout(cct, 0) << "ERROR: failed to sign request" << dendl; - return ret; - } - map& m = new_env.get_map(); map::iterator bliter; @@ -324,13 +388,38 @@ int RGWRESTStreamRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uint64_t for (bliter = attrs.begin(); bliter != attrs.end(); ++bliter) { bufferlist& bl = bliter->second; const string& name = bliter->first; - string val(bl.c_str(), bl.length()); + string val = bl.c_str(); if (name.compare(0, sizeof(RGW_ATTR_META_PREFIX) - 1, RGW_ATTR_META_PREFIX) == 0) { string header_name = RGW_AMZ_META_PREFIX; header_name.append(name.substr(sizeof(RGW_ATTR_META_PREFIX) - 1)); m[header_name] = val; + new_info.x_meta_map[header_name] = val; } } + RGWAccessControlPolicy policy; + int ret = rgw_policy_from_attrset(cct, attrs, &policy); + if (ret < 0) { + ldout(cct, 0) << "ERROR: couldn't get policy ret=" << ret << dendl; + return ret; + } + + /* update acl headers */ + RGWAccessControlList& acl = policy.get_acl(); + multimap& grant_map = acl.get_grant_map(); + multimap::iterator giter; + map grants_by_type; + for (giter = grant_map.begin(); giter != grant_map.end(); ++giter) { + ACLGrant& grant = giter->second; + ACLPermission& perm = grant.get_permission(); + grants_by_type_add_perm(grants_by_type, perm.get_permissions(), grant); + } + add_grants_headers(grants_by_type, m, new_info.x_meta_map); + ret = sign_request(key, new_env, new_info); + if (ret < 0) { + ldout(cct, 0) << "ERROR: failed to sign request" << dendl; + return ret; + } + map::iterator iter; for (iter = m.begin(); iter != m.end(); ++iter) { headers.push_back(make_pair(iter->first, iter->second));