}
}
-
int err;
+ map<string, RGWAccessKey>::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)
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 : "<undefined>")<< std::endl;
#define RGW_BUCKETS_OBJ_PREFIX ".buckets"
-#define USER_INFO_VER 5
+#define USER_INFO_VER 6
#define RGW_MAX_CHUNK_SIZE (4*1024*1024)
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<string, RGWAccessKey> access_keys;
+ map<string, RGWSubUser> subusers;
RGWUserInfo() : auid(0) {}
__u32 ver = USER_INFO_VER;
::encode(ver, bl);
::encode(auid, bl);
+ string access_key;
+ string secret_key;
+ if (!access_keys.empty()) {
+ map<string, RGWAccessKey>::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);
::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);
::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)
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;
}
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<string, RGWAccessKey>::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);
{
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)
}
}
- 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<string, RGWAccessKey>::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;
+ }
}
}
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<string, RGWAccessKey>::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())