]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: multiple swift keys per user
authorYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 11 Oct 2011 17:49:27 +0000 (10:49 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 11 Oct 2011 19:31:48 +0000 (12:31 -0700)
src/rgw/rgw_admin.cc
src/rgw/rgw_common.h
src/rgw/rgw_swift_auth.cc
src/rgw/rgw_user.cc
src/test/cli/radosgw-admin/help.t

index 658cafdf292406234b632e67662c160fd11f1d9c..33e092ddf463dc97e4f3b891e71bd2571c0cab85 100644 (file)
@@ -56,15 +56,14 @@ void _usage()
   cerr << "                             specified date (and optional time)\n";
   cerr << "options:\n";
   cerr << "   --uid=<id>                user id\n";
+  cerr << "   --auth-uid=<auid>         librados uid\n";
   cerr << "   --subuser=<name>          subuser name\n";
   cerr << "   --access-key=<key>        S3 access key\n";
-  cerr << "   --swift-user=<group:name> Swift user\n";
   cerr << "   --email=<email>\n";
-  cerr << "   --auth_uid=<auid>         librados uid\n";
-  cerr << "   --secret=<key>            S3 key\n";
-  cerr << "   --swift-secret=<key>      Swift key\n";
-  cerr << "   --gen-access-key          generate random access key\n";
+  cerr << "   --secret=<key>            specify secret key\n";
+  cerr << "   --gen-access-key          generate random access key (for S3)\n";
   cerr << "   --gen-secret              generate random secret key\n";
+  cerr << "   --key-type=<type>         key type, options are: swift, s3\n";
   cerr << "   --access=<access>         Set access permissions for sub-user, should be one\n";
   cerr << "                             of read, write, readwrite, full\n";
   cerr << "   --display-name=<name>\n";
@@ -291,8 +290,6 @@ static void show_user_info(RGWUserInfo& info, Formatter *formatter)
   formatter->dump_int("rados_uid", info.auid);
   formatter->dump_string("display_name", info.display_name.c_str());
   formatter->dump_string("email", info.user_email.c_str());
-  formatter->dump_string("swift_user", info.swift_name.c_str());
-  formatter->dump_string("swift_key", info.swift_key.c_str());
   formatter->dump_int("suspended", (int)info.suspended);
 
   // keys
@@ -323,6 +320,18 @@ static void show_user_info(RGWUserInfo& info, Formatter *formatter)
   }
   formatter->close_section();
 
+  formatter->open_array_section("swift_keys");
+  for (kiter = info.swift_keys.begin(); kiter != info.swift_keys.end(); ++kiter) {
+    RGWAccessKey& k = kiter->second;
+    const char *sep = (k.subuser.empty() ? "" : ":");
+    const char *subuser = (k.subuser.empty() ? "" : k.subuser.c_str());
+    formatter->open_object_section("key");
+    formatter->dump_format("user", "%s%s%s", info.user_id.c_str(), sep, subuser);
+    formatter->dump_string("secret_key", k.key);
+    formatter->close_section();
+  }
+  formatter->close_section();
+
   formatter->close_section();
   formatter->flush(cout);
 }
@@ -391,12 +400,16 @@ static void remove_old_indexes(RGWUserInfo& old_info, RGWUserInfo new_info)
     }
   }
 
-  if (!old_info.swift_name.empty() &&
-      old_info.swift_name.compare(new_info.swift_name) != 0) {
-    ret = rgw_remove_swift_name_index(new_info.user_id, old_info.swift_name);
-    if (ret < 0 && ret != -ENOENT) {
-      cerr << "ERROR: could not remove index for swift_name " << old_info.swift_name << " return code: " << ret << std::endl;
-      success = false;
+  map<string, RGWAccessKey>::iterator old_iter;
+  for (old_iter = old_info.swift_keys.begin(); old_iter != old_info.swift_keys.end(); ++old_iter) {
+    RGWAccessKey& swift_key = old_iter->second;
+    map<string, RGWAccessKey>::iterator new_iter = new_info.swift_keys.find(swift_key.id);
+    if (new_iter == new_info.swift_keys.end()) {
+      ret = rgw_remove_swift_name_index(new_info.user_id, swift_key.id);
+      if (ret < 0 && ret != -ENOENT) {
+        cerr << "ERROR: could not remove index for swift_name " << swift_key.id << " return code: " << ret << std::endl;
+        success = false;
+      }
     }
   }
 
@@ -443,6 +456,11 @@ int bucket_stats(rgw_bucket& bucket, Formatter *formatter)
   return 0;
 }
 
+enum KeyType {
+  KEY_TYPE_SWIFT,
+  KEY_TYPE_S3,
+};
+
 int main(int argc, char **argv) 
 {
   vector<const char*> args;
@@ -453,8 +471,10 @@ int main(int argc, char **argv)
   common_init_finish(g_ceph_context);
 
   std::string user_id, access_key, secret_key, user_email, display_name;
-  std::string bucket_name, pool_name, object, swift_user, swift_key;
+  std::string bucket_name, pool_name, object;
   std::string date, time, subuser, access, format;
+  std::string key_type_str;
+  KeyType key_type = KEY_TYPE_S3;
   rgw_bucket bucket;
   uint32_t perm_mask = 0;
   uint64_t auid = -1;
@@ -500,6 +520,16 @@ int main(int argc, char **argv)
       pool_name = val;
     } else if (ceph_argparse_witharg(args, i, &val, "-o", "--object", (char*)NULL)) {
       object = val;
+    } else if (ceph_argparse_witharg(args, i, &val, "--key-type", (char*)NULL)) {
+      key_type_str = val;
+      if (key_type_str.compare("swift") == 0) {
+        key_type = KEY_TYPE_SWIFT;
+      } else if (key_type_str.compare("s3") == 0) {
+        key_type = KEY_TYPE_S3;
+      } else {
+        cerr << "bad key type: " << key_type_str << std::endl;
+        return usage();
+      }
     } else if (ceph_argparse_flag(args, i, "--gen-access-key", (char*)NULL)) {
       gen_key = true;
     } else if (ceph_argparse_flag(args, i, "--gen-secret", (char*)NULL)) {
@@ -510,10 +540,6 @@ int main(int argc, char **argv)
        exit(EXIT_FAILURE);
       }
       auid = tmp;
-    } else if (ceph_argparse_witharg(args, i, &val, "--swift-user", (char*)NULL)) {
-      swift_user = val;
-    } else if (ceph_argparse_witharg(args, i, &val, "--swift-secret", (char*)NULL)) {
-      swift_key = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--date", (char*)NULL)) {
       date = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--time", (char*)NULL)) {
@@ -631,13 +657,6 @@ int main(int argc, char **argv)
        cerr << "could not find user by specified access key" << std::endl;
       }
     }
-    if (!found && (!swift_user.empty())) {
-      s = swift_user;
-      if (rgw_get_user_info_by_swift(s, info) >= 0) {
-       found = true;
-      } else
-        cerr << "could not find user by specified swift username" << std::endl;
-    }
     if (found)
       user_id = info.user_id.c_str();
   }
@@ -760,15 +779,23 @@ int main(int argc, char **argv)
   case OPT_KEY_CREATE:
     if (!user_id.empty())
       info.user_id = user_id;
+    if (key_type == KEY_TYPE_SWIFT)
+      access_key = subuser;
     if ((!access_key.empty()) && (!secret_key.empty())) {
       RGWAccessKey k;
       k.id = access_key;
       k.key = secret_key;
       if (!subuser.empty())
         k.subuser = subuser;
-      info.access_keys[access_key] = k;
+      if (key_type == KEY_TYPE_SWIFT)
+        info.swift_keys[access_key] = k;
+      else
+        info.access_keys[access_key] = k;
    } else if ((!access_key.empty()) || (!secret_key.empty())) {
-      cerr << "access key modification requires both access key and secret key" << std::endl;
+      if (key_type == KEY_TYPE_SWIFT)
+        cerr << "swift key modification requires both subuser and secret key" << std::endl;
+      else
+        cerr << "access key modification requires both access key and secret key" << std::endl;
       return 1;
     }
     if (!display_name.empty())
@@ -777,10 +804,6 @@ int main(int argc, char **argv)
       info.user_email = user_email;
     if (auid != (uint64_t)-1)
       info.auid = auid;
-    if (!swift_user.empty())
-      info.swift_name = swift_user;
-    if (!swift_key.empty())
-      info.swift_key = swift_key;
     if (!subuser.empty()) {
       RGWSubUser u;
       u.name = subuser;
index a36e8ec05689f8026afd92a947ccb91932ce4af8..cea557a38f24dbfc48cac62e33363d83805a3694 100644 (file)
@@ -57,7 +57,7 @@ using ceph::crypto::MD5;
 
 #define RGW_BUCKETS_OBJ_PREFIX ".buckets"
 
-#define USER_INFO_VER 7
+#define USER_INFO_VER 8
 
 #define RGW_MAX_CHUNK_SIZE     (512*1024)
 #define RGW_MAX_PENDING_CHUNKS  16
@@ -279,9 +279,8 @@ struct RGWUserInfo
   string user_id;
   string display_name;
   string user_email;
-  string swift_name;
-  string swift_key;
   map<string, RGWAccessKey> access_keys;
+  map<string, RGWAccessKey> swift_keys;
   map<string, RGWSubUser> subusers;
   __u8 suspended;
 
@@ -303,12 +302,21 @@ struct RGWUserInfo
      ::encode(secret_key, bl);
      ::encode(display_name, bl);
      ::encode(user_email, bl);
+     string swift_name;
+     string swift_key;
+     if (!swift_keys.empty()) {
+       map<string, RGWAccessKey>::const_iterator iter = swift_keys.begin();
+       const RGWAccessKey& k = iter->second;
+       swift_name = k.id;
+       swift_key = k.key;
+     }
      ::encode(swift_name, bl);
      ::encode(swift_key, bl);
      ::encode(user_id, bl);
      ::encode(access_keys, bl);
      ::encode(subusers, bl);
      ::encode(suspended, bl);
+     ::encode(swift_keys, bl);
   }
   void decode(bufferlist::iterator& bl) {
      __u32 ver;
@@ -327,6 +335,8 @@ struct RGWUserInfo
     }
     ::decode(display_name, bl);
     ::decode(user_email, bl);
+    string swift_name;
+    string swift_key;
     if (ver >= 3) ::decode(swift_name, bl);
     if (ver >= 4) ::decode(swift_key, bl);
     if (ver >= 5)
@@ -341,6 +351,9 @@ struct RGWUserInfo
     if (ver >= 7) {
       ::decode(suspended, bl);
     }
+    if (ver >= 8) {
+      ::decode(swift_keys, bl);
+    }
   }
 
   void clear() {
index 519c0470b0451e5d468d9dc369eafa2e38aae8cf..41d00111bc72c4e46397cd132bca5eb7bef6d0a4 100644 (file)
@@ -12,9 +12,9 @@ using namespace ceph::crypto;
 
 static RGW_SWIFT_Auth_Get rgw_swift_auth_get;
 
-static int build_token(string& os_user, string& key, uint64_t nonce, utime_t& expiration, bufferlist& bl)
+static int build_token(string& swift_user, string& key, uint64_t nonce, utime_t& expiration, bufferlist& bl)
 {
-  ::encode(os_user, bl);
+  ::encode(swift_user, bl);
   ::encode(nonce, bl);
   ::encode(expiration, bl);
 
@@ -38,7 +38,7 @@ static int build_token(string& os_user, string& key, uint64_t nonce, utime_t& ex
 
 }
 
-static int encode_token(string& os_user, string& key, bufferlist& bl)
+static int encode_token(string& swift_user, string& key, bufferlist& bl)
 {
   uint64_t nonce;
 
@@ -49,7 +49,7 @@ static int encode_token(string& os_user, string& key, bufferlist& bl)
   utime_t expiration = ceph_clock_now(g_ceph_context);
   expiration += RGW_SWIFT_TOKEN_EXPIRATION; // 15 minutes
 
-  ret = build_token(os_user, key, nonce, expiration, bl);
+  ret = build_token(swift_user, key, nonce, expiration, bl);
 
   return ret;
 }
@@ -79,10 +79,10 @@ int rgw_swift_verify_signed_token(const char *token, RGWUserInfo& info)
 
   uint64_t nonce;
   utime_t expiration;
-  string os_user;
+  string swift_user;
 
   try {
-    ::decode(os_user, iter);
+    ::decode(swift_user, iter);
     ::decode(nonce, iter);
     ::decode(expiration, iter);
   } catch (buffer::error& err) {
@@ -94,13 +94,18 @@ int rgw_swift_verify_signed_token(const char *token, RGWUserInfo& info)
     return -EPERM;
   }
 
-  if ((ret = rgw_get_user_info_by_swift(os_user, info)) < 0)
+  if ((ret = rgw_get_user_info_by_swift(swift_user, info)) < 0)
     return ret;
 
-  dout(10) << "os_user=" << os_user << dendl;
+  dout(10) << "swift_user=" << swift_user << dendl;
+
+  map<string, RGWAccessKey>::iterator siter = info.swift_keys.find(swift_user);
+  if (siter == info.swift_keys.end())
+    return -EPERM;
+  RGWAccessKey& swift_key = siter->second;
 
   bufferlist tok;
-  ret = build_token(os_user, info.swift_key, nonce, expiration, tok);
+  ret = build_token(swift_user, swift_key.key, nonce, expiration, tok);
   if (ret < 0)
     return ret;
 
@@ -131,6 +136,8 @@ void RGW_SWIFT_Auth_Get::execute()
   string user_str = user;
   RGWUserInfo info;
   bufferlist bl;
+  RGWAccessKey *swift_key;
+  map<string, RGWAccessKey>::iterator siter;
 
   if (g_conf->rgw_swift_url.length() == 0 ||
       g_conf->rgw_swift_url_prefix.length() == 0) {
@@ -145,7 +152,14 @@ void RGW_SWIFT_Auth_Get::execute()
   if ((ret = rgw_get_user_info_by_swift(user_str, info)) < 0)
     goto done;
 
-  if (info.swift_key.compare(key) != 0) {
+  siter = info.swift_keys.find(user_str);
+  if (siter == info.swift_keys.end()) {
+    ret = -EPERM;
+    goto done;
+  }
+  swift_key = &siter->second;
+
+  if (swift_key->key.compare(key) != 0) {
     dout(0) << "RGW_SWIFT_Auth_Get::execute(): bad swift key" << dendl;
     ret = -EPERM;
     goto done;
@@ -154,7 +168,7 @@ void RGW_SWIFT_Auth_Get::execute()
   CGI_PRINTF(s, "X-Storage-Url: %s/%s/v1/AUTH_rgw\n", g_conf->rgw_swift_url.c_str(),
             g_conf->rgw_swift_url_prefix.c_str());
 
-  if ((ret = encode_token(info.swift_name, info.swift_key, bl)) < 0)
+  if ((ret = encode_token(swift_key->id, swift_key->key, bl)) < 0)
     goto done;
 
   {
index af864c29452d97e228bf21f7baad14fcfb3b65e2..6e056c87f6025092b4beb0c9d6f8b67425c3865a 100644 (file)
@@ -48,10 +48,12 @@ int rgw_store_user_info(RGWUserInfo& info)
   int ret;
   map<string,bufferlist> attrs;
 
-  if (info.swift_name.size()) {
+  map<string, RGWAccessKey>::iterator iter;
+  for (iter = info.swift_keys.begin(); iter != info.swift_keys.end(); ++iter) {
+    RGWAccessKey& k = iter->second;
     /* check if swift mapping exists */
     RGWUserInfo inf;
-    int r = rgw_get_user_info_by_swift(info.swift_name, inf);
+    int r = rgw_get_user_info_by_swift(k.id, inf);
     if (r >= 0 && inf.user_id.compare(info.user_id) != 0) {
       dout(0) << "can't store user info, swift id already mapped to another user" << dendl;
       return -EEXIST;
@@ -98,8 +100,13 @@ int rgw_store_user_info(RGWUserInfo& info)
     }
   }
 
-  if (info.swift_name.size())
-    ret = rgw_put_obj(info.user_id, ui_swift_bucket, info.swift_name, uid_bl.c_str(), uid_bl.length());
+  map<string, RGWAccessKey>::iterator siter;
+  for (siter = info.swift_keys.begin(); siter != info.swift_keys.end(); ++siter) {
+    RGWAccessKey& k = siter->second;
+    ret = rgw_put_obj(info.user_id, ui_swift_bucket, k.id, uid_bl.c_str(), uid_bl.length());
+    if (ret < 0)
+      return ret;
+  }
 
   return ret;
 }
index b0e7699a60f95ceb54b777a3295c80ac6561e49f..d8886e1a48dabdaa78e87f5c524f4910954125c4 100644 (file)
                                specified date (and optional time)
   options:
      --uid=<id>                user id
+     --auth-uid=<auid>         librados uid
      --subuser=<name>          subuser name
      --access-key=<key>        S3 access key
-     --swift-user=<group:name> Swift user
      --email=<email>
-     --auth_uid=<auid>         librados uid
-     --secret=<key>            S3 key
-     --swift-secret=<key>      Swift key
-     --gen-access-key          generate random access key
+     --secret=<key>            specify secret key
+     --gen-access-key          generate random access key (for S3)
      --gen-secret              generate random secret key
+     --key-type=<type>         key type, options are: swift, s3
      --access=<access>         Set access permissions for sub-user, should be one
                                of read, write, readwrite, full
      --display-name=<name>