diff options
author | Yehuda Sadeh <yehuda@hq.newdream.net> | 2011-04-15 17:20:44 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@hq.newdream.net> | 2011-04-15 17:20:44 -0700 |
commit | 544ce94ab9324ebe67ea6d700ec5b6c2ba1a72ea (patch) | |
tree | 2a238d1223921c95c0838a854a6e79c036db344a /src | |
parent | 9b7f223a161388c31b5c7536557dc8632d084315 (diff) | |
download | ceph-544ce94ab9324ebe67ea6d700ec5b6c2ba1a72ea.tar.gz |
rgw: basic support for separate uid and access key
Diffstat (limited to 'src')
-rw-r--r-- | src/rgw/rgw_admin.cc | 27 | ||||
-rw-r--r-- | src/rgw/rgw_common.h | 13 | ||||
-rw-r--r-- | src/rgw/rgw_user.cc | 87 | ||||
-rw-r--r-- | src/rgw/rgw_user.h | 6 |
4 files changed, 89 insertions, 44 deletions
diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 4ca12a1f62f..5c4ea443305 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -34,7 +34,8 @@ void usage() cerr << " policy read bucket/object policy\n"; cerr << " log show dump a log from specific bucket, date\n"; cerr << "options:\n"; - cerr << " --uid=<id> S3 uid\n"; + cerr << " --uid=<id> user id\n"; + cerr << " --s3-key=<id> S3 access key\n"; cerr << " --os-user=<group:name> OpenStack user\n"; cerr << " --email=<email>\n"; cerr << " --auth_uid=<auid> librados uid\n"; @@ -178,6 +179,7 @@ int main(int argc, char **argv) keyring_init(&g_conf); const char *user_id = 0; + const char *access_key = 0; const char *secret_key = 0; const char *user_email = 0; const char *display_name = 0; @@ -196,6 +198,8 @@ int main(int argc, char **argv) FOR_EACH_ARG(args) { if (CEPH_ARGPARSE_EQ("uid", 'i')) { CEPH_ARGPARSE_SET_ARG_VAL(&user_id, OPT_STR); + } else if (CEPH_ARGPARSE_EQ("access-key", '\0')) { + CEPH_ARGPARSE_SET_ARG_VAL(&access_key, OPT_STR); } else if (CEPH_ARGPARSE_EQ("secret", 's')) { CEPH_ARGPARSE_SET_ARG_VAL(&secret_key, OPT_STR); } else if (CEPH_ARGPARSE_EQ("email", 'e')) { @@ -266,15 +270,18 @@ int main(int argc, char **argv) } - if (opt_cmd == OPT_USER_MODIFY || opt_cmd == OPT_USER_INFO || opt_cmd == OPT_BUCKET_UNLINK) { + if (opt_cmd == OPT_USER_CREATE || opt_cmd == OPT_USER_MODIFY || + opt_cmd == OPT_USER_INFO || opt_cmd == OPT_BUCKET_UNLINK) { if (!user_id) { cerr << "user_id was not specified, aborting" << std::endl; - return 0; + usage(); } string user_id_str = user_id; - if (info.user_id.empty() && rgw_get_user_info(user_id_str, info) < 0) { + if (opt_cmd != OPT_USER_CREATE && + info.user_id.empty() && + rgw_get_user_info(user_id_str, info) < 0) { cerr << "error reading user info, aborting" << std::endl; exit(1); } @@ -298,18 +305,19 @@ int main(int argc, char **argv) } secret_key = secret_key_buf; } - if (!user_id) { + if (!access_key) { RGWUserInfo duplicate_check; string duplicate_check_id; + string uid; do { ret = gen_rand_alphanumeric(public_id_buf, sizeof(public_id_buf)); if (ret < 0) { cerr << "aborting" << std::endl; exit(1); } - user_id = public_id_buf; - duplicate_check_id = user_id; - } while (!rgw_get_user_info(duplicate_check_id, duplicate_check)); + access_key = public_id_buf; + duplicate_check_id = access_key; + } while (!rgw_get_uid_by_access_key(duplicate_check_id, uid, duplicate_check)); } } @@ -320,6 +328,8 @@ int main(int argc, char **argv) case OPT_USER_MODIFY: if (user_id) info.user_id = user_id; + if (access_key) + info.access_key = access_key; if (secret_key) info.secret_key = secret_key; if (display_name) @@ -342,6 +352,7 @@ int main(int argc, char **argv) case OPT_USER_INFO: cout << "User ID: " << info.user_id << std::endl; + cout << "Access Key: " << info.access_key << std::endl; cout << "Secret Key: " << info.secret_key << std::endl; cout << "Display Name: " << info.display_name << std::endl; cout << "OpenStack User: " << (info.openstack_name.size() ? info.openstack_name : "<undefined>")<< std::endl; diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index fb160e62f35..39edda3aaee 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -42,7 +42,7 @@ extern string rgw_root_bucket; #define RGW_BUCKETS_OBJ_PREFIX ".buckets" -#define USER_INFO_VER 4 +#define USER_INFO_VER 5 #define RGW_MAX_CHUNK_SIZE (4*1024*1024) @@ -147,6 +147,7 @@ struct RGWUserInfo { uint64_t auid; string user_id; + string access_key; string secret_key; string display_name; string user_email; @@ -159,28 +160,34 @@ struct RGWUserInfo __u32 ver = USER_INFO_VER; ::encode(ver, bl); ::encode(auid, bl); - ::encode(user_id, bl); + ::encode(access_key, bl); ::encode(secret_key, bl); ::encode(display_name, bl); ::encode(user_email, bl); ::encode(openstack_name, bl); ::encode(openstack_key, bl); + ::encode(user_id, bl); } void decode(bufferlist::iterator& bl) { __u32 ver; ::decode(ver, bl); if (ver >= 2) ::decode(auid, bl); else auid = CEPH_AUTH_UID_DEFAULT; - ::decode(user_id, bl); + ::decode(access_key, bl); ::decode(secret_key, bl); ::decode(display_name, bl); ::decode(user_email, bl); if (ver >= 3) ::decode(openstack_name, bl); if (ver >= 4) ::decode(openstack_key, bl); + if (ver >= 5) + ::decode(user_id, bl); + else + user_id = access_key; } void clear() { user_id.clear(); + access_key.clear(); secret_key.clear(); display_name.clear(); user_email.clear(); diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index f82b23741c8..baa4cec4f4f 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -12,9 +12,10 @@ using namespace std; -static string ui_bucket = USER_INFO_BUCKET_NAME; +static string ui_key_bucket = USER_INFO_BUCKET_NAME; static string ui_email_bucket = USER_INFO_EMAIL_BUCKET_NAME; static string ui_openstack_bucket = USER_INFO_OPENSTACK_BUCKET_NAME; +static string ui_uid_bucket = USER_INFO_UID_BUCKET_NAME; string rgw_root_bucket = RGW_ROOT_BUCKET; @@ -33,11 +34,11 @@ int rgw_get_user_info(string user_id, RGWUserInfo& info) int request_len = READ_CHUNK_LEN; time_t lastmod; bufferlist::iterator iter; - ret = rgwstore->prepare_get_obj(ui_bucket, user_id, 0, NULL, NULL, NULL, NULL, &lastmod, NULL, NULL, NULL, &handle, &err); + ret = rgwstore->prepare_get_obj(ui_uid_bucket, user_id, 0, NULL, NULL, NULL, NULL, &lastmod, NULL, NULL, NULL, &handle, &err); if (ret < 0) return ret; do { // we want to read the whole user info in one chunk to avoid any possible race - ret = rgwstore->get_obj(&handle, ui_bucket, user_id, &data, 0, request_len - 1); + ret = rgwstore->get_obj(&handle, ui_uid_bucket, user_id, &data, 0, request_len - 1); if (ret < 0) { goto done; } @@ -69,6 +70,21 @@ void rgw_get_anon_user(RGWUserInfo& info) info.secret_key.clear(); } +static int put_obj(string& uid, string& bucket, string& oid, const char *data, size_t size) +{ + map<string,bufferlist> attrs; + + int ret = rgwstore->put_obj(uid, bucket, oid, data, size, NULL, attrs); + + if (ret == -ENOENT) { + ret = rgwstore->create_bucket(uid, bucket, attrs); + if (ret >= 0) + ret = rgwstore->put_obj(uid, bucket, oid, data, size, NULL, attrs); + } + + return ret; +} + /** * Save the given user information to storage. * Returns: 0 on success, -ERR# on failure. @@ -93,14 +109,18 @@ int rgw_store_user_info(RGWUserInfo& info) } } - ret = rgwstore->put_obj(info.user_id, ui_bucket, info.user_id, data, bl.length(), NULL, attrs); - - if (ret == -ENOENT) { - ret = rgwstore->create_bucket(info.user_id, ui_bucket, attrs); - if (ret >= 0) - ret = rgwstore->put_obj(info.user_id, ui_bucket, info.user_id, data, bl.length(), NULL, attrs); + if (info.access_key.size()) { + /* check if openstack mapping exists */ + string uid; + RGWUserInfo inf; + int r = rgw_get_uid_by_access_key(info.access_key, uid, inf); + if (r >= 0 && uid.compare(info.user_id) != 0) { + RGW_LOG(0) << "can't store user info, access key already mapped to another user" << std::endl; + return -EEXIST; + } } + ret = put_obj(info.user_id, ui_uid_bucket, info.user_id, data, bl.length()); if (ret < 0) return ret; @@ -111,28 +131,20 @@ int rgw_store_user_info(RGWUserInfo& info) ::encode(info, uid_bl); if (info.user_email.size()) { - ret = rgwstore->put_obj(info.user_id, ui_email_bucket, info.user_email, uid_bl.c_str(), uid_bl.length(), NULL, attrs); - if (ret == -ENOENT) { - map<string, bufferlist> attrs; - ret = rgwstore->create_bucket(info.user_id, ui_email_bucket, attrs); - if (ret >= 0) - ret = rgwstore->put_obj(info.user_id, ui_email_bucket, info.user_email, uid_bl.c_str(), uid_bl.length(), NULL, attrs); - } + ret = put_obj(info.user_id, ui_email_bucket, info.user_email, uid_bl.c_str(), uid_bl.length()); + if (ret < 0) + return ret; } - if (ret < 0) - return ret; - - if (info.openstack_name.size()) { - ret = rgwstore->put_obj(info.user_id, ui_openstack_bucket, info.openstack_name, uid_bl.c_str(), uid_bl.length(), NULL, attrs); - if (ret == -ENOENT) { - map<string, bufferlist> attrs; - ret = rgwstore->create_bucket(info.user_id, ui_openstack_bucket, attrs); - if (ret >= 0 && ret != -EEXIST) - ret = rgwstore->put_obj(info.user_id, ui_openstack_bucket, info.openstack_name, uid_bl.c_str(), uid_bl.length(), NULL, attrs); - } + if (info.access_key.size()) { + ret = put_obj(info.access_key, ui_key_bucket, info.access_key, uid_bl.c_str(), uid_bl.length()); + if (ret < 0) + return ret; } + if (info.openstack_name.size()) + ret = put_obj(info.user_id, ui_openstack_bucket, info.openstack_name, uid_bl.c_str(), uid_bl.length()); + return ret; } @@ -194,6 +206,15 @@ extern int rgw_get_uid_by_openstack(string& openstack_name, string& user_id, RGW return rgw_get_uid_from_index(openstack_name, ui_openstack_bucket, user_id, info); } +/** + * Given an access key, finds the user_id associated with it. + * returns: 0 on success, -ERR# on failure (including nonexistence) + */ +extern int rgw_get_uid_by_access_key(string& access_key, string& user_id, RGWUserInfo& info) +{ + return rgw_get_uid_from_index(access_key, ui_key_bucket, user_id, info); +} + static void get_buckets_obj(string& user_id, string& buckets_obj_id) { buckets_obj_id = user_id; @@ -203,7 +224,7 @@ static void get_buckets_obj(string& user_id, string& buckets_obj_id) static int rgw_read_buckets_from_attr(string& user_id, RGWUserBuckets& buckets) { bufferlist bl; - int ret = rgwstore->get_attr(ui_bucket, user_id, RGW_ATTR_BUCKETS, bl); + int ret = rgwstore->get_attr(ui_uid_bucket, user_id, RGW_ATTR_BUCKETS, bl); if (ret) return ret; @@ -240,7 +261,7 @@ int rgw_read_user_buckets(string user_id, RGWUserBuckets& buckets, bool need_sta size_t len = LARGE_ENOUGH_LEN; do { - ret = rgwstore->read(ui_bucket, buckets_obj_id, 0, len, bl); + ret = rgwstore->read(ui_uid_bucket, buckets_obj_id, 0, len, bl); if (ret == -ENOENT) { /* try to read the old format */ ret = rgw_read_buckets_from_attr(user_id, buckets); @@ -309,7 +330,7 @@ int rgw_write_buckets_attr(string user_id, RGWUserBuckets& buckets) bufferlist bl; buckets.encode(bl); - int ret = rgwstore->set_attr(ui_bucket, user_id, RGW_ATTR_BUCKETS, bl); + int ret = rgwstore->set_attr(ui_uid_bucket, user_id, RGW_ATTR_BUCKETS, bl); return ret; } @@ -330,7 +351,7 @@ int rgw_add_bucket(string user_id, string bucket_name) string buckets_obj_id; get_buckets_obj(user_id, buckets_obj_id); - ret = rgwstore->tmap_create(ui_bucket, buckets_obj_id, bucket_name, bl); + ret = rgwstore->tmap_create(ui_uid_bucket, buckets_obj_id, bucket_name, bl); if (ret < 0) { RGW_LOG(0) << "error adding bucket to directory: " << cpp_strerror(-ret)<< std::endl; @@ -370,7 +391,7 @@ int rgw_remove_bucket(string user_id, string bucket_name) string buckets_obj_id; get_buckets_obj(user_id, buckets_obj_id); - ret = rgwstore->tmap_del(ui_bucket, buckets_obj_id, bucket_name); + ret = rgwstore->tmap_del(ui_uid_bucket, buckets_obj_id, bucket_name); if (ret < 0) { RGW_LOG(0) << "error removing bucket from directory: " << cpp_strerror(-ret)<< std::endl; @@ -405,7 +426,7 @@ int rgw_delete_user(RGWUserInfo& info) { string bucket_name = i->first; rgwstore->delete_obj(info.user_id, rgw_root_bucket, bucket_name); } - rgwstore->delete_obj(info.user_id, ui_bucket, info.user_id); + rgwstore->delete_obj(info.user_id, ui_uid_bucket, info.user_id); rgwstore->delete_obj(info.user_id, ui_email_bucket, info.user_email); return 0; } diff --git a/src/rgw/rgw_user.h b/src/rgw/rgw_user.h index 950b0099c73..39216207da2 100644 --- a/src/rgw/rgw_user.h +++ b/src/rgw/rgw_user.h @@ -11,6 +11,7 @@ using namespace std; #define USER_INFO_BUCKET_NAME ".users" #define USER_INFO_EMAIL_BUCKET_NAME ".users.email" #define USER_INFO_OPENSTACK_BUCKET_NAME ".users.openstack" +#define USER_INFO_UID_BUCKET_NAME ".users.uid" #define RGW_USER_ANON_ID "anonymous" /** @@ -54,6 +55,11 @@ extern int rgw_get_uid_by_email(string& email, string& user_id, RGWUserInfo& inf */ extern int rgw_get_uid_by_openstack(string& openstack_name, string& user_id, RGWUserInfo& info); /** + * Given an access key, finds the user_id associated with it. + * returns: 0 on success, -ERR# on failure (including nonexistence) + */ +extern int rgw_get_uid_by_access_key(string& access_key, string& user_id, RGWUserInfo& info); +/** * Given an RGWUserInfo, deletes the user and its bucket ACLs. */ extern int rgw_delete_user(RGWUserInfo& user); |