]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: user info structure supports multiple subusers and keys
authorYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 20 May 2011 22:15:48 +0000 (15:15 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 20 May 2011 22:15:48 +0000 (15:15 -0700)
src/rgw/rgw_admin.cc
src/rgw/rgw_common.h
src/rgw/rgw_os.cc
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_user.cc

index c25dea2fec06dd9f883a9bfe093e9b7d3146802e..5c55d9dee3ae68ee00e832801e87eee5df562618 100644 (file)
@@ -326,17 +326,22 @@ int main(int argc, char **argv)
     }
   }
 
-
   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)
@@ -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 : "<undefined>")<< std::endl;
index 3ed27d01ef4faf5dcd122e922df4434c0fdd2e6c..b4c4774d8aac2390141673dae40413682ab04a48 100644 (file)
@@ -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<string, RGWAccessKey> access_keys;
+  map<string, RGWSubUser> 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<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);
@@ -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)
index 0bf3128b811c7dcc38d836e135a21cefc3134b59..05b8afa40e70161e118d84e24f9f6a93267d8944 100644 (file)
@@ -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;
 }
index 905433f6de9ce7a03d1743f783d41ba2073c74c5..fec2e4702af5fd59a71a3c6d627e6df35a81f38a 100644 (file)
@@ -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<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);
index 055ada6e1f24033d740002606fc2c747a1248c4e..f158b3cf2761d47ecec2aa430bd01dbfa92f0086 100644 (file)
@@ -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<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;
+      }
     }
   }
 
@@ -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<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())