rgw: can use swift to set bucket permissions

Currently only setting, not reading. Also, at the moment it's
setting the wrong permissions.

Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
This commit is contained in:
Yehuda Sadeh 2012-02-23 13:56:22 -08:00
parent 8c48a8e078
commit 2824c07f8d
15 changed files with 291 additions and 34 deletions

View File

@ -335,6 +335,7 @@ my_libradosgw_src = \
rgw/librgw.cc \
rgw/rgw_acl.cc \
rgw/rgw_acl_s3.cc \
rgw/rgw_acl_swift.cc \
rgw/rgw_xml.cc \
rgw/rgw_user.cc \
rgw/rgw_tools.cc \
@ -1426,6 +1427,7 @@ noinst_HEADERS = \
rgw/rgw_access.h\
rgw/rgw_acl.h\
rgw/rgw_acl_s3.h\
rgw/rgw_acl_swift.h\
rgw/rgw_xml.h\
rgw/rgw_cache.h\
rgw/rgw_cls_api.h\

View File

@ -228,6 +228,9 @@ public:
*/
virtual int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl) = 0;
virtual int set_attrs(void *ctx, rgw_obj& obj,
map<string, bufferlist>& attrs,
map<string, bufferlist>* rmattrs) { return -ENOTSUP; }
/**
* stat an object
*/

View File

@ -199,8 +199,10 @@ void ACLGrant_S3::to_xml(ostream& out) {
"<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"" << ACLGranteeType_S3::to_string(type) << "\">";
switch (type.get_type()) {
case ACL_TYPE_CANON_USER:
out << "<ID>" << id << "</ID>" <<
"<DisplayName>" << name << "</DisplayName>";
out << "<ID>" << id << "</ID>";
if (name.size()) {
out << "<DisplayName>" << name << "</DisplayName>";
}
break;
case ACL_TYPE_EMAIL_USER:
out << "<EmailAddress>" << email << "</EmailAddress>";

75
src/rgw/rgw_acl_swift.cc Normal file
View File

@ -0,0 +1,75 @@
#include <string.h>
#include <vector>
#include "rgw_common.h"
#include "rgw_user.h"
#include "rgw_acl_swift.h"
using namespace std;
static int parse_list(string& uid_list, vector<string>& uids)
{
char *s = strdup(uid_list.c_str());
if (!s)
return -ENOMEM;
const char *p = strtok(s, " ,");
while (p) {
if (*p) {
string acl = p;
uids.push_back(acl);
}
p = strtok(NULL, " ,");
}
free(s);
return 0;
}
void RGWAccessControlPolicy_SWIFT::add_grants(vector<string>& uids, int perm)
{
vector<string>::iterator iter;
for (iter = uids.begin(); iter != uids.end(); ++iter ) {
ACLGrant grant;
RGWUserInfo grant_user;
string& uid = *iter;
if (rgw_get_user_info_by_uid(uid, grant_user) < 0) {
dout(10) << "grant user does not exist:" << uid << dendl;
/* skipping silently */
} else {
grant.set_canon(uid, grant_user.display_name, perm);
acl.add_grant(&grant);
}
}
}
bool RGWAccessControlPolicy_SWIFT::create(string& id, string& name, string& read_list, string& write_list)
{
acl.create_default(id, name);
owner.set_id(id);
owner.set_name(name);
if (read_list.size()) {
vector<string> uids;
int r = parse_list(read_list, uids);
if (r < 0) {
dout(0) << "ERROR: parse_list returned r=" << r << dendl;
return false;
}
add_grants(uids, RGW_PERM_READ);
}
if (write_list.size()) {
vector<string> uids;
int r = parse_list(write_list, uids);
if (r < 0) {
dout(0) << "ERROR: parse_list returned r=" << r << dendl;
return false;
}
add_grants(uids, RGW_PERM_WRITE);
}
return true;
}

24
src/rgw/rgw_acl_swift.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef CEPH_RGW_ACL_SWIFT_H
#define CEPH_RGW_ACL_SWIFT3_H
#include <map>
#include <string>
#include <iostream>
#include <vector>
#include <include/types.h>
#include "rgw_acl.h"
using namespace std;
class RGWAccessControlPolicy_SWIFT : public RGWAccessControlPolicy
{
public:
RGWAccessControlPolicy_SWIFT() {}
~RGWAccessControlPolicy_SWIFT() {}
void add_grants(vector<string>& uids, int perm);
bool create(string& id, string& name, string& read_list, string& write_list);
};
#endif

View File

@ -64,7 +64,7 @@ void ObjectCache::put(string& name, ObjectCacheInfo& info)
if (info.flags & CACHE_FLAG_META)
target.meta = info.meta;
else if (!(info.flags & CACHE_FLAG_APPEND_XATTRS))
else if (!(info.flags & CACHE_FLAG_MODIFY_XATTRS))
target.flags &= ~CACHE_FLAG_META; // non-meta change should reset meta
if (info.flags & CACHE_FLAG_XATTRS) {
@ -73,8 +73,12 @@ void ObjectCache::put(string& name, ObjectCacheInfo& info)
for (iter = target.xattrs.begin(); iter != target.xattrs.end(); ++iter) {
dout(10) << "updating xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
}
} else if (info.flags & CACHE_FLAG_APPEND_XATTRS) {
} else if (info.flags & CACHE_FLAG_MODIFY_XATTRS) {
map<string, bufferlist>::iterator iter;
for (iter = info.rm_xattrs.begin(); iter != info.rm_xattrs.end(); ++iter) {
dout(10) << "removing xattr: name=" << iter->first << dendl;
target.xattrs.erase(iter->first);
}
for (iter = info.xattrs.begin(); iter != info.xattrs.end(); ++iter) {
dout(10) << "appending xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
target.xattrs[iter->first] = iter->second;

View File

@ -15,7 +15,7 @@ enum {
#define CACHE_FLAG_DATA 0x1
#define CACHE_FLAG_XATTRS 0x2
#define CACHE_FLAG_META 0x4
#define CACHE_FLAG_APPEND_XATTRS 0x8
#define CACHE_FLAG_MODIFY_XATTRS 0x8
struct ObjectMetaInfo {
uint64_t size;
@ -46,18 +46,20 @@ struct ObjectCacheInfo {
uint32_t flags;
bufferlist data;
map<string, bufferlist> xattrs;
map<string, bufferlist> rm_xattrs;
ObjectMetaInfo meta;
ObjectCacheInfo() : status(0), flags(0) {}
void encode(bufferlist& bl) const {
__u8 struct_v = 1;
__u8 struct_v = 2;
::encode(struct_v, bl);
::encode(status, bl);
::encode(flags, bl);
::encode(data, bl);
::encode(xattrs, bl);
::encode(meta, bl);
::encode(rm_xattrs, bl);
}
void decode(bufferlist::iterator& bl) {
__u8 struct_v;
@ -67,6 +69,8 @@ struct ObjectCacheInfo {
::decode(data, bl);
::decode(xattrs, bl);
::decode(meta, bl);
if (struct_v >= 2)
::decode(rm_xattrs, bl);
}
};
WRITE_CLASS_ENCODER(ObjectCacheInfo)
@ -175,6 +179,9 @@ public:
RGWCache() {}
int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl);
int set_attrs(void *ctx, rgw_obj& obj,
map<string, bufferlist>& attrs,
map<string, bufferlist>* rmattrs);
int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime,
map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,
map<std::string, bufferlist>* rmattrs, const bufferlist *data);
@ -262,7 +269,7 @@ int RGWCache<T>::set_attr(void *ctx, rgw_obj& obj, const char *attr_name, buffer
cacheable = true;
info.xattrs[attr_name] = bl;
info.status = 0;
info.flags = CACHE_FLAG_APPEND_XATTRS;
info.flags = CACHE_FLAG_MODIFY_XATTRS;
}
int ret = T::set_attr(ctx, obj, attr_name, bl);
if (cacheable) {
@ -280,6 +287,40 @@ int RGWCache<T>::set_attr(void *ctx, rgw_obj& obj, const char *attr_name, buffer
return ret;
}
template <class T>
int RGWCache<T>::set_attrs(void *ctx, rgw_obj& obj,
map<string, bufferlist>& attrs,
map<string, bufferlist>* rmattrs)
{
rgw_bucket bucket;
string oid;
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
ObjectCacheInfo info;
bool cacheable = false;
if (bucket.name[0] == '.') {
cacheable = true;
info.xattrs = attrs;
if (rmattrs)
info.rm_xattrs = *rmattrs;
info.status = 0;
info.flags = CACHE_FLAG_MODIFY_XATTRS;
}
int ret = T::set_attrs(ctx, obj, attrs, rmattrs);
if (cacheable) {
string name = normal_name(bucket, oid);
if (ret >= 0) {
cache.put(name, info);
int r = distribute(obj, info, UPDATE_OBJ);
if (r < 0)
dout(0) << "ERROR: failed to distribute cache for " << obj << dendl;
} else {
cache.remove(name);
}
}
return ret;
}
template <class T>
int RGWCache<T>::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime,
map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,

View File

@ -137,7 +137,7 @@ static void format_xattr(std::string &xattr)
* attrs: will be filled up with attrs mapped as <attr_name, attr_contents>
*
*/
static void get_request_metadata(struct req_state *s, map<string, bufferlist>& attrs)
void rgw_get_request_metadata(struct req_state *s, map<string, bufferlist>& attrs)
{
map<string, string>::iterator iter;
for (iter = s->x_meta_map.begin(); iter != s->x_meta_map.end(); ++iter) {
@ -980,7 +980,7 @@ void RGWPutObj::execute()
attrs[RGW_ATTR_CONTENT_TYPE] = bl;
}
get_request_metadata(s, attrs);
rgw_get_request_metadata(s, attrs);
ret = processor->complete(etag, attrs);
done:
@ -991,7 +991,7 @@ done:
return;
}
int RGWPutObjMetadata::verify_permission()
int RGWPutMetadata::verify_permission()
{
if (!verify_object_permission(s, RGW_PERM_WRITE))
return -EACCES;
@ -999,24 +999,26 @@ int RGWPutObjMetadata::verify_permission()
return 0;
}
void RGWPutObjMetadata::execute()
void RGWPutMetadata::execute()
{
ret = -EINVAL;
const char *meta_prefix = RGW_ATTR_META_PREFIX;
int meta_prefix_len = sizeof(RGW_ATTR_META_PREFIX) - 1;
map<string, bufferlist> attrs, orig_attrs, rmattrs;
map<string, bufferlist>::iterator iter;
get_request_metadata(s, attrs);
bufferlist bl;
rgw_obj obj(s->bucket, s->object_str);
rgwstore->set_atomic(s->obj_ctx, obj);
uint64_t obj_size;
ret = get_params();
if (ret < 0)
goto done;
rgw_get_request_metadata(s, attrs);
/* check if obj exists, read orig attrs */
ret = get_obj_attrs(s, obj, orig_attrs, &obj_size);
ret = get_obj_attrs(s, obj, orig_attrs, NULL);
if (ret < 0)
goto done;
@ -1030,7 +1032,11 @@ void RGWPutObjMetadata::execute()
}
}
ret = rgwstore->put_obj_meta(s->obj_ctx, obj, obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, &rmattrs, NULL);
if (has_policy) {
policy.encode(bl);
attrs[RGW_ATTR_ACL] = bl;
}
ret = rgwstore->set_attrs(s->obj_ctx, obj, attrs, &rmattrs);
done:
send_response();
@ -1159,7 +1165,7 @@ int RGWCopyObj::init_common()
dest_policy.encode(aclbl);
attrs[RGW_ATTR_ACL] = aclbl;
get_request_metadata(s, attrs);
rgw_get_request_metadata(s, attrs);
return 0;
}
@ -1341,7 +1347,7 @@ void RGWInitMultipart::execute()
attrs[RGW_ATTR_CONTENT_TYPE] = bl;
}
get_request_metadata(s, attrs);
rgw_get_request_metadata(s, attrs);
do {
char buf[33];

View File

@ -21,6 +21,8 @@ using namespace std;
struct req_state;
class RGWHandler;
void rgw_get_request_metadata(struct req_state *s, map<string, bufferlist>& attrs);
/**
* Provide the base class for all ops.
*/
@ -306,15 +308,19 @@ public:
virtual const char *name() { return "put_obj"; }
};
class RGWPutObjMetadata : public RGWOp {
class RGWPutMetadata : public RGWOp {
protected:
int ret;
map<string, bufferlist> attrs;
bool has_policy;
RGWAccessControlPolicy policy;
public:
RGWPutObjMetadata() {}
RGWPutMetadata() {}
virtual void init(struct req_state *s, RGWHandler *h) {
RGWOp::init(s, h);
has_policy = false;
ret = 0;
}
int verify_permission();

View File

@ -1307,6 +1307,73 @@ int RGWRados::set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl
return 0;
}
int RGWRados::set_attrs(void *ctx, rgw_obj& obj,
map<string, bufferlist>& attrs,
map<string, bufferlist>* rmattrs)
{
rgw_bucket bucket;
std::string oid, key;
get_obj_bucket_and_oid_key(obj, bucket, oid, key);
librados::IoCtx io_ctx;
string actual_obj = oid;
RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
rgw_bucket actual_bucket = bucket;
if (actual_obj.size() == 0) {
actual_obj = bucket.name;
actual_bucket = rgw_root_bucket;
}
int r = open_bucket_ctx(actual_bucket, io_ctx);
if (r < 0)
return r;
io_ctx.locator_set_key(key);
ObjectWriteOperation op;
RGWObjState *state = NULL;
r = append_atomic_test(rctx, obj, io_ctx, actual_obj, op, &state);
if (r < 0)
return r;
map<string, bufferlist>::iterator iter;
if (rmattrs) {
for (iter = rmattrs->begin(); iter != rmattrs->end(); ++iter) {
const string& name = iter->first;
op.rmxattr(name.c_str());
}
}
for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
const string& name = iter->first;
bufferlist& bl = iter->second;
if (!bl.length())
continue;
op.setxattr(name.c_str(), bl);
}
if (!op.size())
return 0;
r = io_ctx.operate(actual_obj, &op);
if (r == -ECANCELED) {
/* a race! object was replaced, we need to set attr on the original obj */
dout(0) << "NOTICE: RGWRados::set_obj_attrs: raced with another process, going to the shadow obj instead" << dendl;
string loc = obj.loc();
rgw_obj shadow(obj.bucket, state->shadow_obj, loc, shadow_ns);
r = set_attrs(NULL, shadow, attrs, rmattrs);
}
if (r < 0)
return r;
return 0;
}
/**
* Get data about an object out of RADOS and into memory.
* bucket: name of the bucket the object is in.

View File

@ -264,6 +264,10 @@ public:
/** Set an attr on an object. */
virtual int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl);
virtual int set_attrs(void *ctx, rgw_obj& obj,
map<string, bufferlist>& attrs,
map<string, bufferlist>* rmattrs);
/** Get data about an object out of RADOS and into memory. */
virtual int prepare_get_obj(void *ctx, rgw_obj& obj,
off_t *ofs, off_t *end,

View File

@ -602,6 +602,7 @@ struct str_len meta_prefixes[] = { STR_LEN_ENTRY("HTTP_X_AMZ"),
STR_LEN_ENTRY("HTTP_X_GOOG"),
STR_LEN_ENTRY("HTTP_X_DHO"),
STR_LEN_ENTRY("HTTP_X_OBJECT"),
STR_LEN_ENTRY("HTTP_X_CONTAINER"),
{NULL, 0} };
static int init_auth_info(struct req_state *s)

View File

@ -67,11 +67,11 @@ public:
int get_data(bufferlist& bl);
};
class RGWPutObjMetadata_REST : public RGWPutObjMetadata
class RGWPutMetadata_REST : public RGWPutMetadata
{
public:
RGWPutObjMetadata_REST() {}
~RGWPutObjMetadata_REST() {}
RGWPutMetadata_REST() {}
~RGWPutMetadata_REST() {}
};
class RGWDeleteObj_REST : public RGWDeleteObj {

View File

@ -2,6 +2,7 @@
#include "common/Formatter.h"
#include "rgw_swift.h"
#include "rgw_rest_swift.h"
#include "rgw_acl_swift.h"
#include <sstream>
@ -309,14 +310,38 @@ void RGWPutObj_REST_SWIFT::send_response()
flush_formatter_to_req_state(s, s->formatter);
}
int RGWPutObjMetadata_REST_SWIFT::get_params()
int RGWPutMetadata_REST_SWIFT::get_params()
{
if (s->has_bad_meta)
return -EINVAL;
if (!s->object) {
string read_list, write_list;
const char *read_attr = s->env->get("HTTP_X_CONTAINER_READ");
if (read_attr) {
read_list = read_attr;
}
const char *write_attr = s->env->get("HTTP_X_CONTAINER_WRITE");
if (write_attr) {
write_list = write_attr;
}
if (read_attr || write_attr) {
RGWAccessControlPolicy_SWIFT swift_policy;
int r = swift_policy.create(s->user.user_id, s->user.display_name, read_list, write_list);
if (r < 0)
return r;
policy = swift_policy;
has_policy = true;
}
}
return 0;
}
void RGWPutObjMetadata_REST_SWIFT::send_response()
void RGWPutMetadata_REST_SWIFT::send_response()
{
if (!ret)
ret = STATUS_ACCEPTED;
@ -415,7 +440,7 @@ int RGWGetObj_REST_SWIFT::send_response(void *handle)
const char *name = iter->first.c_str();
if (strncmp(name, RGW_ATTR_META_PREFIX, sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
name += sizeof(RGW_ATTR_META_PREFIX) - 1;
CGI_PRINTF(s,"X-Object-Meta-%s: %s\r\n", name, iter->second.c_str());
CGI_PRINTF(s,"X-%s-Meta-%s: %s\r\n", (s->object ? "Object" : "Container"), name, iter->second.c_str());
} else if (!content_type && strcmp(name, RGW_ATTR_CONTENT_TYPE) == 0) {
content_type = iter->second.c_str();
}
@ -506,10 +531,7 @@ RGWOp *RGWHandler_REST_SWIFT::get_delete_op()
RGWOp *RGWHandler_REST_SWIFT::get_post_op()
{
if (s->object)
return new RGWPutObjMetadata_REST_SWIFT;
return NULL;
return new RGWPutMetadata_REST_SWIFT;
}
RGWOp *RGWHandler_REST_SWIFT::get_copy_op()

View File

@ -83,10 +83,10 @@ public:
void send_response();
};
class RGWPutObjMetadata_REST_SWIFT : public RGWPutObjMetadata_REST {
class RGWPutMetadata_REST_SWIFT : public RGWPutMetadata_REST {
public:
RGWPutObjMetadata_REST_SWIFT() {}
~RGWPutObjMetadata_REST_SWIFT() {}
RGWPutMetadata_REST_SWIFT() {}
~RGWPutMetadata_REST_SWIFT() {}
int get_params();
void send_response();