From: Radoslaw Zarzynski Date: Fri, 12 Feb 2016 18:49:30 +0000 (+0100) Subject: rgw: add support for caching of Keystone admin token. X-Git-Tag: v10.1.0~282^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=18da92f32b5fd13599bc69c5f5c9ae1215016e5a;p=ceph.git rgw: add support for caching of Keystone admin token. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_keystone.cc b/src/rgw/rgw_keystone.cc index 84d5310162f..7d786050695 100644 --- a/src/rgw/rgw_keystone.cc +++ b/src/rgw/rgw_keystone.cc @@ -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::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); diff --git a/src/rgw/rgw_keystone.h b/src/rgw/rgw_keystone.h index 05f1e6e876a..40a75ee744e 100644 --- a/src/rgw/rgw_keystone.h +++ b/src/rgw/rgw_keystone.h @@ -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::iterator lru_iter; -}; - class RGWKeystoneTokenCache { + struct token_entry { + KeystoneToken token; + list::iterator lru_iter; + }; + CephContext *cct; + string admin_token_id; map tokens; list 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); }; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 105ad8711b8..5e39f5c3f3d 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -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; } diff --git a/src/rgw/rgw_swift.cc b/src/rgw/rgw_swift.cc index 00b55030a3f..aa916ed722b 100644 --- a/src/rgw/rgw_swift.cc +++ b/src/rgw/rgw_swift.cc @@ -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::iterator iter; diff --git a/src/rgw/rgw_swift.h b/src/rgw/rgw_swift.h index c87adee075c..3bffc26dae1 100644 --- a/src/rgw/rgw_swift.h +++ b/src/rgw/rgw_swift.h @@ -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);