rgw: pass grant headers to target when writeing object

When writing object to remote gateway.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
This commit is contained in:
Yehuda Sadeh 2013-06-10 21:59:15 -07:00
parent da5e443c5f
commit ea3efca3fd
4 changed files with 123 additions and 31 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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));