From 2cf5048f6b3f4b5e27a3220624ac741a67eaa4d5 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Fri, 20 May 2011 15:15:48 -0700 Subject: [PATCH] rgw: user info structure supports multiple subusers and keys --- src/rgw/rgw_admin.cc | 23 +++++++++---- src/rgw/rgw_common.h | 76 +++++++++++++++++++++++++++++++++++++++--- src/rgw/rgw_os.cc | 2 +- src/rgw/rgw_rest_s3.cc | 10 ++++-- src/rgw/rgw_user.cc | 30 +++++++++++------ 5 files changed, 115 insertions(+), 26 deletions(-) diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index c25dea2fec06d..5c55d9dee3ae6 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -326,17 +326,22 @@ int main(int argc, char **argv) } } - int err; + map::iterator kiter; switch (opt_cmd) { case OPT_USER_CREATE: 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 (access_key && secret_key) { + RGWAccessKey k; + k.id = access_key; + k.key = secret_key; + info.access_keys[access_key] = k; + } else if (access_key || secret_key) { + cerr << "access key modification requires both access key and secret key" << std::endl; + exit(1); + } if (display_name) info.display_name = display_name; if (user_email) @@ -357,8 +362,12 @@ 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; + for (kiter = info.access_keys.begin(); kiter != info.access_keys.end(); ++kiter) { + RGWAccessKey& k = kiter->second; + cout << "User: " << info.user_id << (k.subuser.empty() ? "" : ":") << k.subuser << std::endl; + cout << " Access Key: " << k.id << std::endl; + cout << " Secret Key: " << k.key << std::endl; + } cout << "Display Name: " << info.display_name << std::endl; cout << "Email: " << info.user_email << std::endl; cout << "OpenStack User: " << (info.openstack_name.size() ? info.openstack_name : "")<< std::endl; diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 3ed27d01ef4fa..b4c4774d8aac2 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -43,7 +43,7 @@ extern string rgw_root_bucket; #define RGW_BUCKETS_OBJ_PREFIX ".buckets" -#define USER_INFO_VER 5 +#define USER_INFO_VER 6 #define RGW_MAX_CHUNK_SIZE (4*1024*1024) @@ -155,17 +155,62 @@ struct fcgx_state { class RGWAccessControlPolicy; +struct RGWAccessKey { + string id; + string key; + string subuser; + + RGWAccessKey() {} + void encode(bufferlist& bl) const { + __u32 ver = 1; + ::encode(ver, bl); + ::encode(id, bl); + ::encode(key, bl); + ::encode(subuser, bl); + } + + void decode(bufferlist::iterator& bl) { + __u32 ver; + ::decode(ver, bl); + ::decode(id, bl); + ::decode(key, bl); + ::decode(subuser, bl); + } +}; +WRITE_CLASS_ENCODER(RGWAccessKey); + +struct RGWSubUser { + string name; + uint32_t flags; + + RGWSubUser() {} + void encode(bufferlist& bl) const { + __u32 ver = 1; + ::encode(ver, bl); + ::encode(name, bl); + ::encode(flags, bl); + } + + void decode(bufferlist::iterator& bl) { + __u32 ver; + ::decode(ver, bl); + ::decode(name, bl); + ::decode(flags, bl); + } +}; +WRITE_CLASS_ENCODER(RGWSubUser); + struct RGWUserInfo { uint64_t auid; string user_id; - string access_key; - string secret_key; string display_name; string user_email; string openstack_name; string openstack_key; + map access_keys; + map subusers; RGWUserInfo() : auid(0) {} @@ -173,6 +218,14 @@ struct RGWUserInfo __u32 ver = USER_INFO_VER; ::encode(ver, bl); ::encode(auid, bl); + string access_key; + string secret_key; + if (!access_keys.empty()) { + map::const_iterator iter = access_keys.begin(); + const RGWAccessKey& k = iter->second; + access_key = k.id; + secret_key = k.key; + } ::encode(access_key, bl); ::encode(secret_key, bl); ::encode(display_name, bl); @@ -180,14 +233,24 @@ struct RGWUserInfo ::encode(openstack_name, bl); ::encode(openstack_key, bl); ::encode(user_id, bl); + ::encode(access_keys, bl); + ::encode(subusers, bl); } void decode(bufferlist::iterator& bl) { __u32 ver; ::decode(ver, bl); if (ver >= 2) ::decode(auid, bl); else auid = CEPH_AUTH_UID_DEFAULT; + string access_key; + string secret_key; ::decode(access_key, bl); ::decode(secret_key, bl); + if (ver < 6) { + RGWAccessKey k; + k.id = access_key; + k.key = secret_key; + access_keys[access_key] = k; + } ::decode(display_name, bl); ::decode(user_email, bl); if (ver >= 3) ::decode(openstack_name, bl); @@ -196,15 +259,18 @@ struct RGWUserInfo ::decode(user_id, bl); else user_id = access_key; + if (ver >= 6) { + ::decode(access_keys, bl); + ::decode(subusers, bl); + } } void clear() { user_id.clear(); - access_key.clear(); - secret_key.clear(); display_name.clear(); user_email.clear(); auid = CEPH_AUTH_UID_DEFAULT; + access_keys.clear(); } }; WRITE_CLASS_ENCODER(RGWUserInfo) diff --git a/src/rgw/rgw_os.cc b/src/rgw/rgw_os.cc index 0bf3128b811c7..05b8afa40e701 100644 --- a/src/rgw/rgw_os.cc +++ b/src/rgw/rgw_os.cc @@ -118,7 +118,7 @@ bool rgw_verify_os_token(req_state *s) return false; } - RGW_LOG(0) << "user_id=" << s->user.user_id << " access_key=" << s->user.access_key << dendl; + RGW_LOG(0) << "user_id=" << s->user.user_id << dendl; return true; } diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 905433f6de9ce..fec2e4702af5f 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -427,8 +427,14 @@ bool RGWHandler_REST_S3::authorize(struct req_state *s) get_auth_header(s, auth_hdr, qsr); RGW_LOG(10) << "auth_hdr:\n" << auth_hdr << dendl; - const char *key = s->user.secret_key.c_str(); - int key_len = strlen(key); + map::iterator iter = s->user.access_keys.find(auth_id); + if (iter == s->user.access_keys.end()) { + RGW_LOG(0) << "ERROR: access key not encoded in user info" << dendl; + return false; + } + RGWAccessKey& k = iter->second; + const char *key = k.key.c_str(); + int key_len = k.key.size(); char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE]; calc_hmac_sha1(key, key_len, auth_hdr.c_str(), auth_hdr.size(), hmac_sha1); diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index 055ada6e1f240..f158b3cf2761d 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -28,7 +28,7 @@ void rgw_get_anon_user(RGWUserInfo& info) { info.user_id = RGW_USER_ANON_ID; info.display_name.clear(); - info.secret_key.clear(); + info.access_keys.clear(); } static int put_obj(string& uid, string& bucket, string& oid, const char *data, size_t size) @@ -68,13 +68,17 @@ int rgw_store_user_info(RGWUserInfo& info) } } - if (info.access_key.size()) { - /* check if openstack mapping exists */ + if (info.access_keys.size()) { + /* check if access keys already exist */ RGWUserInfo inf; - int r = rgw_get_user_info_by_access_key(info.access_key, inf); - if (r >= 0 && inf.user_id.compare(info.user_id) != 0) { - RGW_LOG(0) << "can't store user info, access key already mapped to another user" << dendl; - return -EEXIST; + map::iterator iter = info.access_keys.begin(); + for (; iter != info.access_keys.end(); ++iter) { + RGWAccessKey& k = iter->second; + int r = rgw_get_user_info_by_access_key(k.id, inf); + if (r >= 0 && inf.user_id.compare(info.user_id) != 0) { + RGW_LOG(0) << "can't store user info, access key already mapped to another user" << dendl; + return -EEXIST; + } } } @@ -94,10 +98,14 @@ int rgw_store_user_info(RGWUserInfo& info) return ret; } - 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.access_keys.size()) { + map::iterator iter = info.access_keys.begin(); + for (; iter != info.access_keys.end(); ++iter) { + RGWAccessKey& k = iter->second; + ret = put_obj(k.id, ui_key_bucket, k.id, uid_bl.c_str(), uid_bl.length()); + if (ret < 0) + return ret; + } } if (info.openstack_name.size()) -- 2.39.5