summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@hq.newdream.net>2011-04-15 17:20:44 -0700
committerYehuda Sadeh <yehuda@hq.newdream.net>2011-04-15 17:20:44 -0700
commit544ce94ab9324ebe67ea6d700ec5b6c2ba1a72ea (patch)
tree2a238d1223921c95c0838a854a6e79c036db344a /src
parent9b7f223a161388c31b5c7536557dc8632d084315 (diff)
downloadceph-544ce94ab9324ebe67ea6d700ec5b6c2ba1a72ea.tar.gz
rgw: basic support for separate uid and access key
Diffstat (limited to 'src')
-rw-r--r--src/rgw/rgw_admin.cc27
-rw-r--r--src/rgw/rgw_common.h13
-rw-r--r--src/rgw/rgw_user.cc87
-rw-r--r--src/rgw/rgw_user.h6
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);