librgw: cache RGWUserInfo in rgw_fs private handle

The private RGWLibFS type holds a RGWUserInfo, and
calls rgw_get_user_info_by_access_key and verifies the returned
secret, checks for suspended user, on rgw_mount.

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
This commit is contained in:
Matt Benjamin 2015-10-06 15:36:32 -04:00
parent 6688bc1cce
commit 7e21e2386d
7 changed files with 94 additions and 67 deletions

View File

@ -54,9 +54,6 @@ struct rgw_fs
librgw_t rgw;
void *fs_private;
struct rgw_file_handle root_fh;
char *user_id;
char *access_key_id;
char *secret_access_key;
};

View File

@ -240,12 +240,6 @@ int RGWLibProcess::process_request(RGWLibRequest* req, RGWLibIO* io)
}
#endif
if (s->user->suspended) {
dout(10) << "user is suspended, uid=" << s->user->user_id << dendl;
abort_req(s, op, -ERR_USER_SUSPENDED);
goto done;
}
req->log(s, "reading permissions");
ret = req->read_permissions(op);
if (ret < 0) {

View File

@ -380,6 +380,9 @@ struct RGWAccessKey {
string subuser;
RGWAccessKey() {}
RGWAccessKey(std::string _id, std::string _key)
: id(std::move(_id)), key(std::move(_key)) {}
void encode(bufferlist& bl) const {
ENCODE_START(2, 2, bl);
::encode(id, bl);
@ -489,6 +492,13 @@ struct RGWUserInfo
RGWUserInfo() : auid(0), suspended(0), max_buckets(RGW_DEFAULT_MAX_BUCKETS), op_mask(RGW_OP_TYPE_ALL), system(0) {}
RGWAccessKey* get_key0() {
if (access_keys.empty())
return nullptr;
else
return &(access_keys.begin()->second);
}
void encode(bufferlist& bl) const {
ENCODE_START(17, 9, bl);
::encode(auid, bl);

View File

@ -61,46 +61,34 @@ extern "C" {
/*
attach rgw namespace
*/
int rgw_mount(librgw_t rgw, const char* uid, const char* key,
const char* _secret, struct rgw_fs **rgw_fs)
int rgw_mount(librgw_t rgw, const char *uid, const char *acc_key,
const char *sec_key, struct rgw_fs **rgw_fs)
{
int rc;
string uri(uid);
uri += "\\";
string secret(_secret);
string auth_hdr;
map<string, string> meta_map;
map<string, string> sub_resources;
rgw_create_s3_canonical_header("GET",
NULL, /* const char *content_md5 */
"text/html",
"",
meta_map,
uri.c_str(),
sub_resources,
auth_hdr);
/* check key */
rc = rgw_get_s3_header_digest(auth_hdr, key, secret);
if (rc < 0 ) {
return rc;
}
int rc = 0;
/* stash access data for "mount" */
struct rgw_fs *new_fs =
static_cast<struct rgw_fs*>(operator new (sizeof(struct rgw_fs)));
new_fs->rgw = rgw;
new_fs->user_id = strdup(uid);
new_fs->access_key_id = strdup(key);
new_fs->secret_access_key = strdup(_secret);
RGWLibFS* new_fs = new RGWLibFS(uid, acc_key, sec_key);
assert(new_fs);
rc = new_fs->authorize(librgw.get_store());
if (rc != 0) {
delete new_fs;
return -EINVAL;
}
struct rgw_fs *fs = new_fs->get_fs();;
fs->rgw = rgw;
/* stash the root */
rc = rgw_get_handle("", &new_fs->root_fh);
rc = rgw_get_handle("", &fs->root_fh);
if (rc != 0) {
delete new_fs;
return -EINVAL;
}
*rgw_fs = new_fs;
*rgw_fs = fs;
return rc;
return 0;
}
/*
@ -108,11 +96,8 @@ int rgw_mount(librgw_t rgw, const char* uid, const char* key,
*/
int rgw_umount(struct rgw_fs *rgw_fs)
{
free(rgw_fs->user_id);
free(rgw_fs->access_key_id);
free(rgw_fs->secret_access_key);
operator delete (rgw_fs);
RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
delete fs;
return 0;
}
@ -296,6 +281,7 @@ int rgw_readdir(struct rgw_fs *rgw_fs,
return rc;
}
RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
CephContext* cct = static_cast<CephContext*>(rgw_fs->rgw);
/* TODO:
@ -305,7 +291,7 @@ int rgw_readdir(struct rgw_fs *rgw_fs,
*/
if (is_root(uri)) {
/* for now, root always contains one user's bucket namespace */
RGWListBucketsRequest req(cct, rgw_fs->user_id, rcb, cb_arg, offset);
RGWListBucketsRequest req(cct, fs->get_user(), rcb, cb_arg, offset);
(void) librgw.get_fe()->execute_req(&req);
} else {
/*
@ -313,7 +299,7 @@ int rgw_readdir(struct rgw_fs *rgw_fs,
*/
uri += "/";
RGWListBucketRequest req(cct, rgw_fs->user_id, uri, rcb, cb_arg, offset);
RGWListBucketRequest req(cct, fs->get_user(), uri, rcb, cb_arg, offset);
(void) librgw.get_fe()->execute_req(&req);
}

View File

@ -22,14 +22,33 @@ public:
class RGWLibFS
{
struct rgw_fs fs;
// XXX auth caching
std::string uid; // should match user.user_id, iiuc
RGWUserInfo user;
RGWAccessKey key;
public:
RGWLibFS() {
RGWLibFS(const char *_uid, const char *_user_id, const char* _key)
: uid(_uid), key(_user_id, _key) {
fs.fs_private = this;
}
int authorize(RGWRados* store) {
int ret = rgw_get_user_info_by_access_key(store, key.id, user);
if (ret == 0) {
RGWAccessKey* key0 = user.get_key0();
if (!key0 ||
(key0->key != key.key))
return -EINVAL;
if (user.suspended)
return -ERR_USER_SUSPENDED;
}
return 0;
}
struct rgw_fs* get_fs() { return &fs; }
RGWUserInfo* get_user() { return &user; }
}; /* RGWLibFS */
@ -41,14 +60,14 @@ class RGWListBucketsRequest : public RGWLibRequest,
public RGWListBuckets_ObjStore_Lib /* RGWOp */
{
public:
std::string user_id;
RGWUserInfo* user;
uint64_t* offset;
void* cb_arg;
rgw_readdir_cb rcb;
RGWListBucketsRequest(CephContext* _cct, char *_user_id,
RGWListBucketsRequest(CephContext* _cct, RGWUserInfo *_user,
rgw_readdir_cb _rcb, void* _cb_arg, uint64_t* _offset)
: RGWLibRequest(_cct), user_id(_user_id), offset(_offset), cb_arg(_cb_arg),
: RGWLibRequest(_cct), user(_user), offset(_offset), cb_arg(_cb_arg),
rcb(_rcb) {
magic = 71;
op = this;
@ -79,9 +98,8 @@ public:
s->info.request_params = "";
s->info.domain = ""; /* XXX ? */
/* XXX fake user_id (will fix) */
s->user->user_id = user_id;
s->user->display_name = user_id;
// woo
s->user = user;
return 0;
}
@ -101,15 +119,15 @@ class RGWListBucketRequest : public RGWLibRequest,
public RGWListBucket_ObjStore_Lib /* RGWOp */
{
public:
std::string user_id;
RGWUserInfo* user;
std::string& uri;
uint64_t* offset;
void* cb_arg;
rgw_readdir_cb rcb;
RGWListBucketRequest(CephContext* _cct, char *_user_id, std::string& _uri,
RGWListBucketRequest(CephContext* _cct, RGWUserInfo *_user, std::string& _uri,
rgw_readdir_cb _rcb, void* _cb_arg, uint64_t* _offset)
: RGWLibRequest(_cct), user_id(_user_id), uri(_uri), offset(_offset),
: RGWLibRequest(_cct), user(_user), uri(_uri), offset(_offset),
cb_arg(_cb_arg),
rcb(_rcb) {
magic = 72;
@ -141,10 +159,8 @@ public:
s->info.request_params = "";
s->info.domain = ""; /* XXX ? */
/* XXX fake user_id and perms (will fix) */
s->user->user_id = user_id;
s->user->display_name = user_id;
s->perm_mask = RGW_PERM_READ;
// woo
s->user = user;
return 0;
}

View File

@ -105,12 +105,13 @@ class RGWLibRequest : public RGWRequest,
public RGWHandler_Lib {
public:
CephContext* cct;
RGWUserInfo* user;
/* unambiguiously return req_state */
inline struct req_state* get_state() { return this->RGWRequest::s; }
RGWLibRequest(CephContext* _cct)
: RGWRequest(0), cct(_cct)
: RGWRequest(0), cct(_cct), user(nullptr)
{}
/* descendant equivalent of *REST*::init_from_header(...):

View File

@ -27,8 +27,8 @@
namespace {
librgw_t rgw = nullptr;
string uid("testuser");
string access_key("C4B4D3E4H355VTDTQXRF");
string secret_key("NRBkhM2rUZNUbydD86HpNJ110VpQjVroumCOHJXw");
string access_key("");
string secret_key("");
struct rgw_fs *fs = nullptr;
typedef std::tuple<string,uint64_t, struct rgw_file_handle*> fid_type; //in c++2014 can alias...
std::vector<fid_type> fids1;
@ -60,6 +60,9 @@ TEST(LibRGW, LIST_BUCKETS) {
/* list buckets via readdir in fs root */
using std::get;
if (! fs)
return;
bool eof = false;
uint64_t offset = 0;
int ret = rgw_readdir(fs, &fs->root_fh, &offset, r1_cb, &fids1, &eof);
@ -81,6 +84,9 @@ extern "C" {
TEST(LibRGW, LOOKUP_BUCKETS) {
using std::get;
if (! fs)
return;
int ret = 0;
for (auto& fid : fids1) {
struct rgw_file_handle *rgw_fh = new rgw_file_handle();
@ -95,6 +101,9 @@ TEST(LibRGW, LIST_OBJECTS) {
/* list objects via readdir, bucketwise */
using std::get;
if (! fs)
return;
for (auto& fid : fids1) {
std::cout << "readdir in bucket " << get<0>(fid) << std::endl;
bool eof = false;
@ -119,6 +128,9 @@ TEST(LibRGW, CLEANUP) {
}
TEST(LibRGW, UMOUNT) {
if (! fs)
return;
int ret = rgw_umount(fs);
ASSERT_EQ(ret, 0);
}
@ -129,12 +141,23 @@ TEST(LibRGW, SHUTDOWN) {
int main(int argc, char *argv[])
{
char *v{nullptr};
string val;
vector<const char*> args;
argv_to_vec(argc, const_cast<const char**>(argv), args);
env_to_vec(args);
v = getenv("AWS_ACCESS_KEY_ID");
if (v) {
access_key = v;
}
v = getenv("AWS_SECRET_ACCESS_KEY");
if (v) {
secret_key = v;
}
for (auto arg_iter = args.begin(); arg_iter != args.end();) {
if (ceph_argparse_witharg(args, arg_iter, &val, "--access",
(char*) NULL)) {