]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add support for caching of Keystone admin token.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Fri, 12 Feb 2016 18:49:30 +0000 (19:49 +0100)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Thu, 25 Feb 2016 17:34:16 +0000 (18:34 +0100)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_keystone.cc
src/rgw/rgw_keystone.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_swift.cc
src/rgw/rgw_swift.h

index 84d5310162fe70e247edd92be797a72605dd9722..7d7860506952c2c3de2c11072de1606208e8fa41 100644 (file)
@@ -151,7 +151,9 @@ bool KeystoneToken::has_role(const string& r)
   return false;
 }
 
-int KeystoneToken::parse(CephContext *cct, bufferlist& bl)
+int KeystoneToken::parse(CephContext * const cct,
+                         const string& token_str,
+                         bufferlist& bl)
 {
   JSONParser parser;
   if (!parser.parse(bl.c_str(), bl.length())) {
@@ -167,11 +169,17 @@ int KeystoneToken::parse(CephContext *cct, bufferlist& bl)
         /* Token structure doesn't follow Identity API v2, so the token
          * must be in v3. Otherwise we can assume it's wrongly formatted. */
         JSONDecoder::decode_json("token", *this, &parser, true);
+        token.id = token_str;
       }
     } else if (version == KeystoneApiVersion::VER_2) {
       if (!JSONDecoder::decode_json("token", *this, &parser)) {
         /* If the token cannot be parsed according to V2, try V3. */
         JSONDecoder::decode_json("access", *this, &parser, true);
+      } else {
+        /* v3 suceeded. We have to fill token.id from external input as it
+         * isn't a part of the JSON response anymore. It has been moved
+         * to X-Subject-Token HTTP header instead. */
+        token.id = token_str;
       }
     } else {
       return -ENOTSUP;
@@ -214,7 +222,15 @@ bool RGWKeystoneTokenCache::find(const string& token_id, KeystoneToken& token)
   return true;
 }
 
-void RGWKeystoneTokenCache::add(const string& token_id, KeystoneToken& token)
+bool RGWKeystoneTokenCache::find_admin(KeystoneToken& token)
+{
+  Mutex::Locker l(lock);
+
+  return find(admin_token_id, token);
+}
+
+void RGWKeystoneTokenCache::add(const string& token_id,
+                                const KeystoneToken& token)
 {
   lock.Lock();
   map<string, token_entry>::iterator iter = tokens.find(token_id);
@@ -239,6 +255,14 @@ void RGWKeystoneTokenCache::add(const string& token_id, KeystoneToken& token)
   lock.Unlock();
 }
 
+void RGWKeystoneTokenCache::add_admin(const KeystoneToken& token)
+{
+  Mutex::Locker l(lock);
+
+  get_token_id(token.token.id, admin_token_id);
+  add(admin_token_id, token);
+}
+
 void RGWKeystoneTokenCache::invalidate(const string& token_id)
 {
   Mutex::Locker l(lock);
index 05f1e6e876afb79132e165c8b3f050adf7393408..40a75ee744ebe5bf2f3e94ea0bce3b9f5302d179 100644 (file)
@@ -83,18 +83,21 @@ public:
     uint64_t now = ceph_clock_now(NULL).sec();
     return (now >= (uint64_t)get_expires());
   }
-  int parse(CephContext *cct, bufferlist& bl);
+  int parse(CephContext *cct,
+            const string& token_str,
+            bufferlist& bl /* in */);
   void decode_json(JSONObj *access_obj);
 };
 
-struct token_entry {
-  KeystoneToken token;
-  list<string>::iterator lru_iter;
-};
-
 class RGWKeystoneTokenCache {
+  struct token_entry {
+    KeystoneToken token;
+    list<string>::iterator lru_iter;
+  };
+
   CephContext *cct;
 
+  string admin_token_id;
   map<string, token_entry> tokens;
   list<string> tokens_lru;
 
@@ -103,10 +106,16 @@ class RGWKeystoneTokenCache {
   size_t max;
 
 public:
-  RGWKeystoneTokenCache(CephContext *_cct, int _max) : cct(_cct), lock("RGWKeystoneTokenCache"), max(_max) {}
+  RGWKeystoneTokenCache(CephContext *_cct, int _max)
+    : cct(_cct),
+      lock("RGWKeystoneTokenCache", true /* recursive */),
+      max(_max) {
+  }
 
   bool find(const string& token_id, KeystoneToken& token);
-  void add(const string& token_id, KeystoneToken& token);
+  bool find_admin(KeystoneToken& token);
+  void add(const string& token_id, const KeystoneToken& token);
+  void add_admin(const KeystoneToken& token);
   void invalidate(const string& token_id);
 };
 
index 105ad8711b8ba829eb2d4148027f3c255d1a46df..5e39f5c3f3dc15e371a3cba0b1169299b51f08c9 100644 (file)
@@ -2803,7 +2803,7 @@ int RGW_Auth_S3_Keystone_ValidateToken::validate_s3token(
   }
 
   /* now parse response */
-  if (response.parse(cct, rx_buffer) < 0) {
+  if (response.parse(cct, string(), rx_buffer) < 0) {
     dout(2) << "s3 keystone: token parsing failed" << dendl;
     return -EPERM;
   }
index 00b55030a3f21e7ac8401c2aaafdb7c9f5a9d94b..aa916ed722b3d78a8c9903e5ade6b848a194e30e 100644 (file)
@@ -209,12 +209,24 @@ int RGWSwift::get_keystone_admin_token(CephContext * const cct,
 {
   std::string token_url;
 
-  if (get_keystone_url(cct, token_url) < 0)
+  if (get_keystone_url(cct, token_url) < 0) {
     return -EINVAL;
+  }
+
   if (!cct->_conf->rgw_keystone_admin_token.empty()) {
     token = cct->_conf->rgw_keystone_admin_token;
     return 0;
   }
+
+  KeystoneToken t;
+
+  /* Try cache first. */
+  if (keystone_token_cache->find_admin(t)) {
+    ldout(cct, 20) << "found cached admin token" << dendl;
+    token = t.token.id;
+    return 0;
+  }
+
   bufferlist token_bl;
   RGWGetKeystoneAdminToken token_req(cct, &token_bl);
   token_req.append_header("Content-Type", "application/json");
@@ -230,14 +242,7 @@ int RGWSwift::get_keystone_admin_token(CephContext * const cct,
     token_req.set_post_data(ss.str());
     token_req.set_send_length(ss.str().length());
     token_url.append("v2.0/tokens");
-    int ret = token_req.process("POST", token_url.c_str());
-    if (ret < 0)
-      return ret;
-    KeystoneToken t;
-    if (t.parse(cct, token_bl) != 0)
-      return -EINVAL;
-    token = t.token.id;
-    return 0;
+
   } else if (keystone_version == KeystoneApiVersion::VER_3) {
     KeystoneAdminTokenRequestVer3 req_serializer(cct);
     req_serializer.dump(&jf);
@@ -247,13 +252,21 @@ int RGWSwift::get_keystone_admin_token(CephContext * const cct,
     token_req.set_post_data(ss.str());
     token_req.set_send_length(ss.str().length());
     token_url.append("v3/auth/tokens");
-    int ret = token_req.process("POST", token_url.c_str());
-    if (ret < 0)
-      return ret;
-    token = token_req.get_subject_token();
-    return 0;
+  } else {
+    return -ENOTSUP;
+  }
+
+  const int ret = token_req.process("POST", token_url.c_str());
+  if (ret < 0) {
+    return ret;
   }
-  return -EINVAL;
+  if (t.parse(cct, token_req.get_subject_token(), token_bl) != 0) {
+    return -EINVAL;
+  }
+
+  keystone_token_cache->add_admin(t);
+  token = t.token.id;
+  return 0;
 }
 
 
@@ -362,11 +375,15 @@ static void rgw_set_keystone_token_auth_info(KeystoneToken& token, struct rgw_sw
   info->status = 200;
 }
 
-int RGWSwift::parse_keystone_token_response(const string& token, bufferlist& bl, struct rgw_swift_auth_info *info, KeystoneToken& t)
+int RGWSwift::parse_keystone_token_response(const string& token,
+                                            bufferlist& bl,
+                                            struct rgw_swift_auth_info *info,
+                                            KeystoneToken& t)
 {
-  int ret = t.parse(cct, bl);
-  if (ret < 0)
+  int ret = t.parse(cct, token, bl);
+  if (ret < 0) {
     return ret;
+  }
 
   bool found = false;
   list<string>::iterator iter;
index c87adee075c6ca7d428f689c4800747ac063ca7f..3bffc26dae1a37870864962fbbc3fbc5d9979e23 100644 (file)
@@ -31,7 +31,9 @@ class RGWSwift {
   int validate_keystone_token(RGWRados *store, const string& token, struct rgw_swift_auth_info *info,
                              RGWUserInfo& rgw_user);
 
-  int parse_keystone_token_response(const string& token, bufferlist& bl, struct rgw_swift_auth_info *info,
+  int parse_keystone_token_response(const string& token,
+                                    bufferlist& bl,
+                                    struct rgw_swift_auth_info *info,
                                    KeystoneToken& t);
   int update_user_info(RGWRados *store, struct rgw_swift_auth_info *info, RGWUserInfo& user_info);
   int get_keystone_url(std::string& url);