diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-10 21:59:15 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-10 21:59:15 -0700 |
commit | ea3efca3fd161d9ed56df3c28f558ce593aae470 (patch) | |
tree | c6667551c1dcc889493ab6300dd457233de37ed4 | |
parent | da5e443c5f263c3fa3bdde21783a715685da7e03 (diff) | |
download | ceph-ea3efca3fd161d9ed56df3c28f558ce593aae470.tar.gz |
rgw: pass grant headers to target when writeing object
When writing object to remote gateway.
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r-- | src/rgw/rgw_op.cc | 25 | ||||
-rw-r--r-- | src/rgw/rgw_rados.cc | 24 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 2 | ||||
-rw-r--r-- | src/rgw/rgw_rest_client.cc | 103 |
4 files changed, 123 insertions, 31 deletions
diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index f571de0f731..86618bd674b 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<string, bufferlist>& attrset, RGWAccessControlPolicy *policy) -{ - map<string, bufferlist>::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<RGWAccessControlPolicy_S3 *>(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 0583ba014bc..a9a4815036a 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<string, bufferlist>& attrset, RGWAccessControlPolicy *policy) +{ + map<string, bufferlist>::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<RGWAccessControlPolicy_S3 *>(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 d6897823794..cee93e913c0 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<string, bufferlist>& attrset, RGWAccessControlPolicy *policy); + struct RGWUsageBatch { map<utime_t, rgw_usage_log_entry> m; diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc index c7e11a95841..e3e1c0ba7f8 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<int, string>& 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<int, string>& 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<int, string>& 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<int, string>& grants, map<string, string>& attrs, map<string, string>& meta_map) +{ + struct grant_type_to_header *t; + + for (t = grants_headers_def; t->header; t++) { + map<int, string>::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<string, bufferlist>& 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<string, string>& m = new_env.get_map(); map<string, bufferlist>::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<string, ACLGrant>& grant_map = acl.get_grant_map(); + multimap<string, ACLGrant>::iterator giter; + map<int, string> 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<string, string>::iterator iter; for (iter = m.begin(); iter != m.end(); ++iter) { headers.push_back(make_pair<string, string>(iter->first, iter->second)); |