diff options
author | Christophe Courtaut <christophe.courtaut@gmail.com> | 2013-07-03 20:48:12 +0200 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-08-25 17:57:16 -0700 |
commit | 59f1fa7027a6a7d5e793727fd360ba1dea57ee90 (patch) | |
tree | c057c8312030832ac4ceccca1b0bf89197c36fe1 | |
parent | 2184ec135076456cad9dee7724d31c158edcfcf2 (diff) | |
download | ceph-59f1fa7027a6a7d5e793727fd360ba1dea57ee90.tar.gz |
rgw: Adds passwd alternative to keystone admin token
http://tracker.ceph.com/issues/5374 Fixes #5374
This adds options parsing to have a user, password and tenant,
to be able to ask for a token.
This token is then used to authenticate against keystone, instead
of relying on the admin token.
Otherwise, you can still use the admin token to authenticate.
This doesn't change the existing behaviour.
Signed-off-by: Christophe Courtaut <christophe.courtaut@gmail.com>
-rw-r--r-- | src/common/config_opts.h | 3 | ||||
-rw-r--r-- | src/rgw/rgw_swift.cc | 112 | ||||
-rw-r--r-- | src/rgw/rgw_swift.h | 3 |
3 files changed, 111 insertions, 7 deletions
diff --git a/src/common/config_opts.h b/src/common/config_opts.h index 89405121698..dfb0d14aa68 100644 --- a/src/common/config_opts.h +++ b/src/common/config_opts.h @@ -651,6 +651,9 @@ OPTION(rgw_swift_auth_url, OPT_STR, "") // default URL to go and verify t OPTION(rgw_swift_auth_entry, OPT_STR, "auth") // entry point for which a url is considered a swift auth url OPTION(rgw_keystone_url, OPT_STR, "") // url for keystone server OPTION(rgw_keystone_admin_token, OPT_STR, "") // keystone admin token (shared secret) +OPTION(rgw_keystone_admin_user, OPT_STR, "") // keystone admin token (shared secret) +OPTION(rgw_keystone_admin_password, OPT_STR, "") // keystone admin token (shared secret) +OPTION(rgw_keystone_admin_tenant, OPT_STR, "") // keystone admin token (shared secret) OPTION(rgw_keystone_accepted_roles, OPT_STR, "Member, admin") // roles required to serve requests OPTION(rgw_keystone_token_cache_size, OPT_INT, 10000) // max number of entries in keystone token cache OPTION(rgw_keystone_revocation_interval, OPT_INT, 15 * 60) // seconds between tokens revocation check diff --git a/src/rgw/rgw_swift.cc b/src/rgw/rgw_swift.cc index b62033b2764..71c0ea002dc 100644 --- a/src/rgw/rgw_swift.cc +++ b/src/rgw/rgw_swift.cc @@ -166,6 +166,11 @@ int KeystoneToken::parse(CephContext *cct, bufferlist& bl) return -EINVAL; } + if (!token->get_data("id", &token_id)) { + ldout(cct, 0) << "token response is missing id field" << dendl; + return -EINVAL; + } + string expires; if (!token->get_data("expires", &expires)) { @@ -292,6 +297,37 @@ void RGWKeystoneTokenCache::invalidate(const string& token_id) tokens.erase(iter); } +class RGWGetKeystoneAdminToken : public RGWHTTPClient { + bufferlist *bl; + std::string post_data; + size_t post_data_index; +public: + RGWGetKeystoneAdminToken(bufferlist *_bl) : bl(_bl), post_data_index(0) {} + + void set_post_data(std::string _post_data) { + this->post_data = _post_data; + } + + int receive_header(void *ptr, size_t len) { + return 0; + } + int receive_data(void *ptr, size_t len) { + bl->append((char *)ptr, len); + return 0; + } + + int send_data(void* ptr, size_t len) { + int length_to_copy = 0; + if (post_data_index < post_data.length()) + { + length_to_copy = min(post_data.length() - post_data_index, len); + memcpy(ptr, post_data.data() + post_data_index, length_to_copy); + post_data_index += length_to_copy; + } + return length_to_copy; + } +}; + class RGWValidateKeystoneToken : public RGWHTTPClient { bufferlist *bl; public: @@ -314,8 +350,14 @@ static RGWKeystoneTokenCache *keystone_token_cache = NULL; class RGWGetRevokedTokens : public RGWHTTPClient { bufferlist *bl; + std::string post_data; + size_t post_data_index; public: - RGWGetRevokedTokens(CephContext *_cct, bufferlist *_bl) : RGWHTTPClient(_cct), bl(_bl) {} + RGWGetRevokedTokens(CephContext *_cct, bufferlist *_bl) : RGWHTTPClient(_cct), bl(_bl), post_data_index(0) {} + + void set_post_data(std::string _post_data) { + this->post_data = _post_data; + } int receive_data(void *ptr, size_t len) { bl->append((char *)ptr, len); @@ -324,8 +366,15 @@ public: int receive_header(void *ptr, size_t len) { return 0; } - int send_data(void *ptr, size_t len) { - return 0; + int send_data(void* ptr, size_t len) { + int length_to_copy = 0; + if (post_data_index < post_data.length()) + { + length_to_copy = min(post_data.length() - post_data_index, len); + memcpy(ptr, post_data.data() + post_data_index, length_to_copy); + post_data_index += length_to_copy; + } + return length_to_copy; } }; @@ -397,23 +446,72 @@ static int decode_b64_cms(CephContext *cct, const string& signed_b64, bufferlist return 0; } - -int RGWSwift::check_revoked() +int RGWSwift::get_keystone_url(std::string& url) { bufferlist bl; RGWGetRevokedTokens req(cct, &bl); string url = g_conf->rgw_keystone_url; + if (url.empty()) { ldout(cct, 0) << "ERROR: keystone url is not configured" << dendl; return -EINVAL; } if (url[url.size() - 1] != '/') url.append("/"); - url.append("v2.0/tokens/revoked"); + return 0; +} + +int RGWSwift::get_keystone_admin_token(std::string& token) +{ + std::string token_url; + + if (get_keystone_url(token_url) != 0) + return -EINVAL; + if (g_conf->rgw_keystone_admin_token.empty()) { + token_url.append("v2.0/tokens"); + KeystoneToken t; + bufferlist token_bl; + RGWGetKeystoneAdminToken token_req(&token_bl); + JSONFormatter jf; + jf.open_object_section("auth"); + jf.open_object_section("passwordCredentials"); + encode_json("username", g_conf->rgw_keystone_admin_user, &jf); + encode_json("password", g_conf->rgw_keystone_admin_password, &jf); + jf.close_section(); + encode_json("tenantName", g_conf->rgw_keystone_admin_tenant, &jf); + jf.close_section(); + std::stringstream ss; + jf.flush(ss); + token_req.set_post_data(ss.str()); + int ret = token_req.process(token_url.c_str()); + if (ret < 0) + return ret; + token_bl.append((char)0); // NULL terminate for debug output + if (t.parse(cct, token_bl) != 0) + return -EINVAL; + token = t.token_id; + } + else + token = g_conf->rgw_keystone_admin_token; + return 0; +} + + +int RGWSwift::check_revoked() +{ + string url; + string token; - req.append_header("X-Auth-Token", g_conf->rgw_keystone_admin_token); + bufferlist bl; + RGWGetRevokedTokens req(&bl); + if (get_keystone_admin_token(token) != 0) + return -EINVAL; + if (get_keystone_url(url) != 0) + return -EINVAL; + url.append("v2.0/tokens/revoked"); + req.append_header("X-Auth-Token", token); int ret = req.process(url.c_str()); if (ret < 0) return ret; diff --git a/src/rgw/rgw_swift.h b/src/rgw/rgw_swift.h index febc2675c27..b334b9b640e 100644 --- a/src/rgw/rgw_swift.h +++ b/src/rgw/rgw_swift.h @@ -22,6 +22,7 @@ public: string tenant_name; string tenant_id; string user_name; + string token_id; time_t expiration; map<string, bool> roles; @@ -47,6 +48,8 @@ class RGWSwift { 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); + int get_keystone_admin_token(std::string& token); class KeystoneRevokeThread : public Thread { CephContext *cct; |