mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
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:
parent
6688bc1cce
commit
7e21e2386d
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(...):
|
||||
|
@ -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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user