]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: keystone tokens revocation thread
authorYehuda Sadeh <yehuda@inktank.com>
Tue, 6 Nov 2012 01:29:52 +0000 (17:29 -0800)
committerYehuda Sadeh <yehuda@inktank.com>
Thu, 8 Nov 2012 21:24:29 +0000 (13:24 -0800)
Use a thread to invalidate revoked tokens.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/common/config_opts.h
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_swift.cc
src/rgw/rgw_swift.h

index 6a3117947c623829eded7e9c6ffc6cd8c5021c0b..c9c5b4943b6881ed09a679b72ff99c49a82b6be5 100644 (file)
@@ -428,6 +428,7 @@ 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_operator_roles, OPT_STR, "swiftoperator, 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
 OPTION(rgw_admin_entry, OPT_STR, "admin")  // entry point for which a url is considered an admin request
 OPTION(rgw_enforce_swift_acls, OPT_BOOL, true)
 OPTION(rgw_print_continue, OPT_BOOL, true)  // enable if 100-Continue works
index d3d45e5525c318265f8a6eccdb84606d08895f0a..753adc86e424e7cb0563005a88fe56e2c13b73f4 100644 (file)
@@ -610,7 +610,7 @@ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_copy()
 
 int RGWHandler_ObjStore_SWIFT::authorize()
 {
-  bool authorized = rgw_verify_swift_token(store, s);
+  bool authorized = rgw_swift->verify_swift_token(store, s);
   if (!authorized)
     return -EPERM;
 
index df075e97b7e83a02491c559cdadfcfe4aafc2ac8..060b435dfa4649419450e46a14ba4e3aae919e4b 100644 (file)
@@ -21,12 +21,13 @@ static list<string> roles_list;
 class RGWKeystoneTokenCache;
 
 class RGWValidateSwiftToken : public RGWHTTPClient {
+  CephContext *cct;
   struct rgw_swift_auth_info *info;
 
 protected:
-  RGWValidateSwiftToken() {}
+  RGWValidateSwiftToken() : cct(NULL), info(NULL) {}
 public:
-  RGWValidateSwiftToken(struct rgw_swift_auth_info *_info) : info(_info) {}
+  RGWValidateSwiftToken(CephContext *_cct, struct rgw_swift_auth_info *_info) : cct(_cct), info(_info) {}
 
   int read_header(void *ptr, size_t len);
 
@@ -39,7 +40,7 @@ int RGWValidateSwiftToken::read_header(void *ptr, size_t len)
 
   char *s = (char *)ptr, *end = (char *)ptr + len;
   char *p = line;
-  dout(10) << "read_http_header" << dendl;
+  ldout(cct, 10) << "read_http_header" << dendl;
 
   while (s != end) {
     if (*s == '\r') {
@@ -48,7 +49,7 @@ int RGWValidateSwiftToken::read_header(void *ptr, size_t len)
     }
     if (*s == '\n') {
       *p = '\0';
-      dout(10) << "os_auth:" << line << dendl;
+      ldout(cct, 10) << "os_auth:" << line << dendl;
       // TODO: fill whatever data required here
       char *l = line;
       char *tok = strsep(&l, " \t:");
@@ -76,7 +77,7 @@ int RGWValidateSwiftToken::read_header(void *ptr, size_t len)
   return 0;
 }
 
-static int rgw_swift_validate_token(const char *token, struct rgw_swift_auth_info *info)
+int RGWSwift::validate_token(const char *token, struct rgw_swift_auth_info *info)
 {
   if (g_conf->rgw_swift_auth_url.empty())
     return -EINVAL;
@@ -88,9 +89,9 @@ static int rgw_swift_validate_token(const char *token, struct rgw_swift_auth_inf
   char url_buf[auth_url.size() + 1 + strlen(token) + 1];
   sprintf(url_buf, "%s/%s", auth_url.c_str(), token);
 
-  RGWValidateSwiftToken validate(info);
+  RGWValidateSwiftToken validate(cct, info);
 
-  dout(10) << "rgw_swift_validate_token url=" << url_buf << dendl;
+  ldout(cct, 10) << "rgw_swift_validate_token url=" << url_buf << dendl;
 
   int ret = validate.process(url_buf);
   if (ret < 0)
@@ -99,74 +100,55 @@ static int rgw_swift_validate_token(const char *token, struct rgw_swift_auth_inf
   return 0;
 }
 
-class KeystoneToken {
-public:
-  string tenant_name;
-  string tenant_id;
-  string user_name;
-  time_t expiration;
-
-  map<string, bool> roles;
-
-  KeystoneToken() {}
-
-  int parse(bufferlist& bl);
-
-  bool expired() {
-    uint64_t now = ceph_clock_now(NULL).sec();
-    return (now < (uint64_t)expiration);
-  }
-};
-
-int KeystoneToken::parse(bufferlist& bl)
+int KeystoneToken::parse(CephContext *cct, bufferlist& bl)
 {
   RGWJSONParser parser;
 
   if (!parser.parse(bl.c_str(), bl.length())) {
-    dout(0) << "malformed json" << dendl;
+    ldout(cct, 0) << "malformed json" << dendl;
     return -EINVAL;
   }
 
   JSONObjIter iter = parser.find_first("access");
   if (iter.end()) {
-    dout(0) << "token response is missing access section" << dendl;
+    ldout(cct, 0) << "token response is missing access section" << dendl;
     return -EINVAL;
   }  
 
   JSONObj *access_obj = *iter;
   JSONObj *user = access_obj->find_obj("user");
   if (!user) {
-    dout(0) << "token response is missing user section" << dendl;
+    ldout(cct, 0) << "token response is missing user section" << dendl;
     return -EINVAL;
   }
 
   if (!user->get_data("username", &user_name)) {
-    dout(0) << "token response is missing user username field" << dendl;
+    ldout(cct, 0) << "token response is missing user username field" << dendl;
     return -EINVAL;
   }
 
   JSONObj *roles_obj = user->find_obj("roles");
   if (!roles_obj) {
-    dout(0) << "token response is missing roles section, or section empty" << dendl;
+    ldout(cct, 0) << "token response is missing roles section, or section empty" << dendl;
     return -EINVAL;
   }
 
   JSONObjIter riter = roles_obj->find_first();
   if (riter.end()) {
-    dout(0) << "token response has an empty roles list" << dendl;
+    ldout(cct, 0) << "token response has an empty roles list" << dendl;
     return -EINVAL;
   }
 
   for (; !riter.end(); ++riter) {
     JSONObj *role_obj = *riter;
     if (!role_obj) {
-      dout(0) << "ERROR: role object is NULL" << dendl;
+      ldout(cct, 0) << "ERROR: role object is NULL" << dendl;
       return -EINVAL;
     }
 
     JSONObj *role_name = role_obj->find_obj("name");
     if (!role_name) {
-      dout(0) << "token response is missing role name section" << dendl;
+      ldout(cct, 0) << "token response is missing role name section" << dendl;
       return -EINVAL;
     }
     string role = role_name->get_data();
@@ -175,20 +157,20 @@ int KeystoneToken::parse(bufferlist& bl)
 
   JSONObj *token = access_obj->find_obj("token");
   if (!token) {
-    dout(0) << "missing token section in response" << dendl;
+    ldout(cct, 0) << "missing token section in response" << dendl;
     return -EINVAL;
   }
 
   string expires;
 
   if (!token->get_data("expires", &expires)) {
-    dout(0) << "token response is missing expiration field" << dendl;
+    ldout(cct, 0) << "token response is missing expiration field" << dendl;
     return -EINVAL;
   }
 
   struct tm t;
   if (!parse_iso8601(expires.c_str(), &t)) {
-    dout(0) << "failed to parse token expiration (" << expires << ")" << dendl;
+    ldout(cct, 0) << "failed to parse token expiration (" << expires << ")" << dendl;
     return -EINVAL;
   }
 
@@ -196,18 +178,18 @@ int KeystoneToken::parse(bufferlist& bl)
 
   JSONObj *tenant = token->find_obj("tenant");
   if (!tenant) {
-    dout(0) << "token response is missing tenant section" << dendl;
+    ldout(cct, 0) << "token response is missing tenant section" << dendl;
     return -EINVAL;
   }
 
   if (!tenant->get_data("id", &tenant_id)) {
-    dout(0) << "tenant is missing id field" << dendl;
+    ldout(cct, 0) << "tenant is missing id field" << dendl;
     return -EINVAL;
   }
 
 
   if (!tenant->get_data("name", &tenant_name)) {
-    dout(0) << "tenant is missing name field" << dendl;
+    ldout(cct, 0) << "tenant is missing name field" << dendl;
     return -EINVAL;
   }
 
@@ -220,6 +202,8 @@ struct token_entry {
 };
 
 class RGWKeystoneTokenCache {
+  CephContext *cct;
+
   map<string, token_entry> tokens;
   list<string> tokens_lru;
 
@@ -228,7 +212,7 @@ class RGWKeystoneTokenCache {
   size_t max;
 
 public:
-  RGWKeystoneTokenCache(int _max) : lock("RGWKeystoneTokenCache"), max(_max) {}
+  RGWKeystoneTokenCache(CephContext *_cct, int _max) : cct(_cct), lock("RGWKeystoneTokenCache"), max(_max) {}
 
   bool find(const string& token_id, KeystoneToken& token);
   void add(const string& token_id, KeystoneToken& token);
@@ -297,7 +281,7 @@ void RGWKeystoneTokenCache::invalidate(const string& token_id)
   if (iter == tokens.end())
     return;
 
-  dout(20) << "invalidating revoked token id=" << token_id << dendl;
+  ldout(cct, 20) << "invalidating revoked token id=" << token_id << dendl;
   token_entry& e = iter->second;
   tokens_lru.erase(e.lru_iter);
   tokens.erase(iter);
@@ -326,21 +310,22 @@ public:
     return 0;
   }
 };
-static int open_cms_envelope(string& src, string& dst)
+
+static int open_cms_envelope(CephContext *cct, string& src, string& dst)
 {
 #define BEGIN_CMS "-----BEGIN CMS-----"
 #define END_CMS "-----END CMS-----"
 
   int start = src.find(BEGIN_CMS);
   if (start < 0) {
-    dout(0) << "failed to find " << BEGIN_CMS << " in response" << dendl;
+    ldout(cct, 0) << "failed to find " << BEGIN_CMS << " in response" << dendl;
     return -EINVAL;
   }
   start += sizeof(BEGIN_CMS) - 1;
 
   int end = src.find(END_CMS);
   if (end < 0) {
-    dout(0) << "failed to find " << END_CMS << " in response" << dendl;
+    ldout(cct, 0) << "failed to find " << END_CMS << " in response" << dendl;
     return -EINVAL;
   }
 
@@ -362,7 +347,7 @@ static int open_cms_envelope(string& src, string& dst)
   return 0;
 }
 
-static int decode_b64_cms(const string& signed_b64, bufferlist& bl)
+static int decode_b64_cms(CephContext *cct, const string& signed_b64, bufferlist& bl)
 {
   bufferptr signed_ber(signed_b64.size() * 2);
   char *dest = signed_ber.c_str();
@@ -378,7 +363,7 @@ static int decode_b64_cms(const string& signed_b64, bufferlist& bl)
   }
   int ret = ceph_unarmor(dest, dest + signed_ber.length(), buf, buf + signed_b64.size());
   if (ret < 0) {
-    dout(0) << "ceph_unarmor() failed, ret=" << ret << dendl;
+    ldout(cct, 0) << "ceph_unarmor() failed, ret=" << ret << dendl;
     return ret;
   }
 
@@ -387,7 +372,7 @@ static int decode_b64_cms(const string& signed_b64, bufferlist& bl)
 
   ret = ceph_decode_cms(signed_ber_bl, bl);
   if (ret < 0) {
-    dout(0) << "ceph_decode_cms returned " << ret << dendl;
+    ldout(cct, 0) << "ceph_decode_cms returned " << ret << dendl;
     return ret;
   }
 
@@ -395,14 +380,14 @@ static int decode_b64_cms(const string& signed_b64, bufferlist& bl)
 }
 
 
-static int rgw_check_revoked()
+int RGWSwift::check_revoked()
 {
   bufferlist bl;
   RGWGetRevokedTokens req(&bl);
 
   string url = g_conf->rgw_keystone_url;
   if (url.empty()) {
-    dout(0) << "ERROR: keystone url is not configured" << dendl;
+    ldout(cct, 0) << "ERROR: keystone url is not configured" << dendl;
     return -EINVAL;
   }
   if (url[url.size() - 1] != '/')
@@ -417,18 +402,18 @@ static int rgw_check_revoked()
 
   bl.append((char)0); // NULL terminate for debug output
 
-  dout(10) << "request returned " << bl.c_str() << dendl;
+  ldout(cct, 10) << "request returned " << bl.c_str() << dendl;
 
   RGWJSONParser parser;
 
   if (!parser.parse(bl.c_str(), bl.length())) {
-    dout(0) << "malformed json" << dendl;
+    ldout(cct, 0) << "malformed json" << dendl;
     return -EINVAL;
   }
 
   JSONObjIter iter = parser.find_first("signed");
   if (iter.end()) {
-    dout(0) << "revoked tokens response is missing signed section" << dendl;
+    ldout(cct, 0) << "revoked tokens response is missing signed section" << dendl;
     return -EINVAL;
   }  
 
@@ -436,32 +421,32 @@ static int rgw_check_revoked()
 
   string signed_str = signed_obj->get_data();
 
-  dout(10) << "signed=" << signed_str << dendl;
+  ldout(cct, 10) << "signed=" << signed_str << dendl;
 
   string signed_b64;
-  ret = open_cms_envelope(signed_str, signed_b64);
+  ret = open_cms_envelope(cct, signed_str, signed_b64);
   if (ret < 0)
     return ret;
 
-  dout(10) << "content=" << signed_b64 << dendl;
+  ldout(cct, 10) << "content=" << signed_b64 << dendl;
   
   bufferlist json;
-  ret = decode_b64_cms(signed_b64, json);
+  ret = decode_b64_cms(cct, signed_b64, json);
   if (ret < 0) {
     return ret;
   }
 
-  dout(10) << "ceph_decode_cms: decoded: " << json.c_str() << dendl;
+  ldout(cct, 10) << "ceph_decode_cms: decoded: " << json.c_str() << dendl;
 
   RGWJSONParser list_parser;
   if (!list_parser.parse(json.c_str(), json.length())) {
-    dout(0) << "malformed json" << dendl;
+    ldout(cct, 0) << "malformed json" << dendl;
     return -EINVAL;
   }
 
   JSONObjIter revoked_iter = list_parser.find_first("revoked");
   if (revoked_iter.end()) {
-    dout(0) << "no revoked section in json" << dendl;
+    ldout(cct, 0) << "no revoked section in json" << dendl;
     return -EINVAL;
   }
 
@@ -473,7 +458,7 @@ static int rgw_check_revoked()
 
     JSONObj *token = o->find_obj("id");
     if (!token) {
-      dout(0) << "bad token in array, missing id" << dendl;
+      ldout(cct, 0) << "bad token in array, missing id" << dendl;
       continue;
     }
 
@@ -491,10 +476,9 @@ static void rgw_set_keystone_token_auth_info(KeystoneToken& token, struct rgw_sw
   info->status = 200;
 }
 
-static int rgw_parse_keystone_token_response(const string& token, bufferlist& bl, struct rgw_swift_auth_info *info)
+int RGWSwift::parse_keystone_token_response(const string& token, bufferlist& bl, struct rgw_swift_auth_info *info, KeystoneToken& t)
 {
-  KeystoneToken t;
-  int ret = t.parse(bl);
+  int ret = t.parse(cct, bl);
   if (ret < 0)
     return ret;
 
@@ -509,27 +493,27 @@ static int rgw_parse_keystone_token_response(const string& token, bufferlist& bl
   }
 
   if (!found) {
-    dout(0) << "user does not hold a matching role; required roles: " << g_conf->rgw_keystone_operator_roles << dendl;
+    ldout(cct, 0) << "user does not hold a matching role; required roles: " << g_conf->rgw_keystone_operator_roles << dendl;
     return -EPERM;
   }
 
-  dout(0) << "validated token: " << t.tenant_name << ":" << t.user_name << " expires: " << t.expiration << dendl;
+  ldout(cct, 0) << "validated token: " << t.tenant_name << ":" << t.user_name << " expires: " << t.expiration << dendl;
 
   rgw_set_keystone_token_auth_info(t, info);
 
   return 0;
 }
 
-static int update_user_info(RGWRados *store, struct rgw_swift_auth_info *info, RGWUserInfo& user_info)
+int RGWSwift::update_user_info(RGWRados *store, struct rgw_swift_auth_info *info, RGWUserInfo& user_info)
 {
   if (rgw_get_user_info_by_uid(store, info->user, user_info) < 0) {
-    dout(0) << "NOTICE: couldn't map swift user" << dendl;
+    ldout(cct, 0) << "NOTICE: couldn't map swift user" << dendl;
     user_info.user_id = info->user;
     user_info.display_name = info->display_name;
 
     int ret = rgw_store_user_info(store, user_info, true);
     if (ret < 0) {
-      dout(0) << "ERROR: failed to store new user's info: ret=" << ret << dendl;
+      ldout(cct, 0) << "ERROR: failed to store new user's info: ret=" << ret << dendl;
       return ret;
     }
   }
@@ -560,36 +544,37 @@ static void get_token_id(const string& token, string& token_id)
   char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
   buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5);
   token_id = calc_md5;
-
-  dout(0) << "token_id=" << token_id << dendl;
 }
 
-static bool decode_pki_token(const string& token, bufferlist& bl)
+static bool decode_pki_token(CephContext *cct, const string& token, bufferlist& bl)
 {
   if (!is_pki_token(token))
     return false;
 
-  int ret = decode_b64_cms(token, bl);
+  int ret = decode_b64_cms(cct, token, bl);
   if (ret < 0)
     return false;
 
-  dout(20) << "successfully decoded pki token" << dendl;
+  ldout(cct, 20) << "successfully decoded pki token" << dendl;
 
   return true;
 }
 
-static int rgw_swift_validate_keystone_token(RGWRados *store, const string& token, struct rgw_swift_auth_info *info,
-                                            RGWUserInfo& rgw_user)
+int RGWSwift::validate_keystone_token(RGWRados *store, const string& token, struct rgw_swift_auth_info *info,
+                                     RGWUserInfo& rgw_user)
 {
   KeystoneToken t;
 
-  rgw_check_revoked();
-
   string token_id;
   get_token_id(token, token_id);
 
+  ldout(cct, 20) << "token_id=" << token_id << dendl;
+
   if (keystone_token_cache->find(token_id, t)) {
     rgw_set_keystone_token_auth_info(t, info);
+
+    ldout(cct, 20) << "cached token.tenant_id=" << t.tenant_id << dendl;
+
     int ret = update_user_info(store, info, rgw_user);
     if (ret < 0)
       return ret;
@@ -599,12 +584,12 @@ static int rgw_swift_validate_keystone_token(RGWRados *store, const string& toke
 
   bufferlist bl;
 
-  if (!decode_pki_token(token, bl)) {
+  if (!decode_pki_token(cct, token, bl)) {
     RGWValidateKeystoneToken validate(&bl);
 
     string url = g_conf->rgw_keystone_url;
     if (url.empty()) {
-      dout(0) << "ERROR: keystone url is not configured" << dendl;
+      ldout(cct, 0) << "ERROR: keystone url is not configured" << dendl;
       return -EINVAL;
     }
     if (url[url.size() - 1] != '/')
@@ -621,14 +606,12 @@ static int rgw_swift_validate_keystone_token(RGWRados *store, const string& toke
 
   bl.append((char)0); // NULL terminate for debug output
 
-  dout(20) << "received response: " << bl.c_str() << dendl;
+  ldout(cct, 20) << "received response: " << bl.c_str() << dendl;
 
-  int ret = rgw_parse_keystone_token_response(token, bl, info);
+  int ret = parse_keystone_token_response(token, bl, info, t);
   if (ret < 0)
     return ret;
 
-  keystone_token_cache->add(token_id, t);
-
   ret = update_user_info(store, info, rgw_user);
   if (ret < 0)
     return ret;
@@ -637,7 +620,7 @@ static int rgw_swift_validate_keystone_token(RGWRados *store, const string& toke
 }
 
 
-bool rgw_verify_swift_token(RGWRados *store, req_state *s)
+bool RGWSwift::verify_swift_token(RGWRados *store, req_state *s)
 {
   if (!s->os_auth_token)
     return false;
@@ -657,16 +640,16 @@ bool rgw_verify_swift_token(RGWRados *store, req_state *s)
   int ret;
 
   if (g_conf->rgw_swift_use_keystone) {
-    ret = rgw_swift_validate_keystone_token(store, s->os_auth_token, &info, s->user);
+    ret = validate_keystone_token(store, s->os_auth_token, &info, s->user);
     return (ret >= 0);
   }
 
-  ret = rgw_swift_validate_token(s->os_auth_token, &info);
+  ret = validate_token(s->os_auth_token, &info);
   if (ret < 0)
     return ret;
 
   if (info.user.empty()) {
-    dout(5) << "swift auth didn't authorize a user" << dendl;
+    ldout(cct, 5) << "swift auth didn't authorize a user" << dendl;
     return false;
   }
 
@@ -675,29 +658,82 @@ bool rgw_verify_swift_token(RGWRados *store, req_state *s)
 
   string swift_user = s->swift_user;
 
-  dout(10) << "swift user=" << s->swift_user << dendl;
+  ldout(cct, 10) << "swift user=" << s->swift_user << dendl;
 
   if (rgw_get_user_info_by_swift(store, swift_user, s->user) < 0) {
-    dout(0) << "NOTICE: couldn't map swift user" << dendl;
+    ldout(cct, 0) << "NOTICE: couldn't map swift user" << dendl;
     return false;
   }
 
-  dout(10) << "user_id=" << s->user.user_id << dendl;
+  ldout(cct, 10) << "user_id=" << s->user.user_id << dendl;
 
   return true;
 }
 
-void swift_init(CephContext *cct)
+void RGWSwift::init()
 {
   get_str_list(cct->_conf->rgw_keystone_operator_roles, roles_list);
 
-  keystone_token_cache = new RGWKeystoneTokenCache(cct->_conf->rgw_keystone_token_cache_size);
+  keystone_token_cache = new RGWKeystoneTokenCache(cct, cct->_conf->rgw_keystone_token_cache_size);
+
+  keystone_revoke_thread = new KeystoneRevokeThread(cct, this);
+  keystone_revoke_thread->create();
 }
 
 
-void swift_finalize()
+void RGWSwift::finalize()
 {
   delete keystone_token_cache;
   keystone_token_cache = NULL;
+
+  down_flag.set(1);
+  if (keystone_revoke_thread) {
+    keystone_revoke_thread->stop();
+    keystone_revoke_thread->join();
+  }
+  delete keystone_revoke_thread;
+  keystone_revoke_thread = NULL;
+}
+
+RGWSwift *rgw_swift = NULL;
+
+void swift_init(CephContext *cct)
+{
+  rgw_swift = new RGWSwift(cct);
+}
+
+void swift_finalize()
+{
+  delete rgw_swift;
+}
+
+bool RGWSwift::going_down()
+{
+  return (down_flag.read() != 0);
+}
+
+void *RGWSwift::KeystoneRevokeThread::entry() {
+  do {
+    dout(2) << "keystone revoke thread: start" << dendl;
+    int r = swift->check_revoked();
+    if (r < 0) {
+      dout(0) << "ERROR: keystone revocation processing returned error r=" << r << dendl;
+    }
+
+    if (swift->going_down())
+      break;
+
+    lock.Lock();
+    cond.WaitInterval(cct, lock, utime_t(cct->_conf->rgw_keystone_revocation_interval, 0));
+    lock.Unlock();
+  } while (!swift->going_down());
+
+  return NULL;
+}
+
+void RGWSwift::KeystoneRevokeThread::stop()
+{
+  Mutex::Locker l(lock);
+  cond.Signal();
 }
 
index 80149b62393ae78f1d11cafddcda0fc717a50915..bdca5b46283e62b2a0e62377cbe5db22db1f5b60 100644 (file)
@@ -3,6 +3,7 @@
 #define CEPH_RGW_SWIFT_H
 
 #include "rgw_common.h"
+#include "common/Cond.h"
 
 class RGWRados;
 
@@ -16,8 +17,69 @@ struct rgw_swift_auth_info {
   rgw_swift_auth_info() : status(0), ttl(0) {}
 };
 
-bool rgw_verify_swift_token(RGWRados *store, req_state *s);
+class KeystoneToken {
+public:
+  string tenant_name;
+  string tenant_id;
+  string user_name;
+  time_t expiration;
 
+  map<string, bool> roles;
+
+  KeystoneToken() {}
+
+  int parse(CephContext *cct, bufferlist& bl);
+
+  bool expired() {
+    uint64_t now = ceph_clock_now(NULL).sec();
+    return (now < (uint64_t)expiration);
+  }
+};
+
+class RGWSwift {
+  CephContext *cct;
+  atomic_t down_flag;
+
+  int validate_token(const char *token, struct rgw_swift_auth_info *info);
+  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,
+                                   KeystoneToken& t);
+  int update_user_info(RGWRados *store, struct rgw_swift_auth_info *info, RGWUserInfo& user_info);
+
+  class KeystoneRevokeThread : public Thread {
+    CephContext *cct;
+    RGWSwift *swift;
+    Mutex lock;
+    Cond cond;
+
+  public:
+    KeystoneRevokeThread(CephContext *_cct, RGWSwift *_swift) : cct(_cct), swift(_swift), lock("KeystoneRevokeThread") {}
+    void *entry();
+    void stop();
+  };
+
+  KeystoneRevokeThread *keystone_revoke_thread;
+
+  void init();
+  void finalize();
+protected:
+  int check_revoked();
+public:
+
+  RGWSwift(CephContext *_cct) : cct(_cct) {
+    init();
+  }
+  ~RGWSwift() {
+    finalize();
+  }
+
+  bool verify_swift_token(RGWRados *store, req_state *s);
+  bool going_down();
+};
+
+extern RGWSwift *rgw_swift;
 void swift_init(CephContext *cct);
 void swift_finalize();