summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-06-10 21:59:15 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-06-10 21:59:15 -0700
commitea3efca3fd161d9ed56df3c28f558ce593aae470 (patch)
treec6667551c1dcc889493ab6300dd457233de37ed4
parentda5e443c5f263c3fa3bdde21783a715685da7e03 (diff)
downloadceph-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.cc25
-rw-r--r--src/rgw/rgw_rados.cc24
-rw-r--r--src/rgw/rgw_rados.h2
-rw-r--r--src/rgw/rgw_rest_client.cc103
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));