From 94226bdd39a64415e456057740add0ee6190d033 Mon Sep 17 00:00:00 2001 From: Clay Gerrard Date: Mon, 2 May 2022 17:28:03 -0500 Subject: [PATCH] Don't give clients made up tokens If we can't set the token in memcache return the client a service unavailable error. Change-Id: I33a672f49dc09886f26b58f4fef6916d11f69547 --- swift/common/middleware/tempauth.py | 42 +++++++++++++------- test/unit/common/middleware/test_tempauth.py | 9 +++++ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/swift/common/middleware/tempauth.py b/swift/common/middleware/tempauth.py index 151a754acd..850c7830eb 100644 --- a/swift/common/middleware/tempauth.py +++ b/swift/common/middleware/tempauth.py @@ -183,9 +183,10 @@ import base64 from eventlet import Timeout import six +from swift.common.memcached import MemcacheConnectionError from swift.common.swob import Response, Request, wsgi_to_str from swift.common.swob import HTTPBadRequest, HTTPForbidden, HTTPNotFound, \ - HTTPUnauthorized, HTTPMethodNotAllowed + HTTPUnauthorized, HTTPMethodNotAllowed, HTTPServiceUnavailable from swift.common.request_helpers import get_sys_meta_prefix from swift.common.middleware.acl import ( @@ -690,7 +691,7 @@ class TempAuth(object): self.logger.increment('errors') start_response('500 Server Error', [('Content-Type', 'text/plain')]) - return ['Internal server error.\n'] + return [b'Internal server error.\n'] def handle_request(self, req): """ @@ -720,6 +721,25 @@ class TempAuth(object): req.response = handler(req) return req.response + def _create_new_token(self, memcache_client, + account, account_user, account_id): + # Generate new token + token = '%stk%s' % (self.reseller_prefix, uuid4().hex) + expires = time() + self.token_life + groups = self._get_user_groups(account, account_user, account_id) + # Save token + memcache_token_key = '%s/token/%s' % (self.reseller_prefix, token) + memcache_client.set(memcache_token_key, (expires, groups), + time=float(expires - time()), + raise_on_error=True) + # Record the token with the user info for future use. + memcache_user_key = \ + '%s/user/%s' % (self.reseller_prefix, account_user) + memcache_client.set(memcache_user_key, token, + time=float(expires - time()), + raise_on_error=True) + return token, expires + def handle_get_token(self, req): """ Handles the various `request for token and service end point(s)` calls. @@ -827,19 +847,11 @@ class TempAuth(object): token = candidate_token # Create a new token if one didn't exist if not token: - # Generate new token - token = '%stk%s' % (self.reseller_prefix, uuid4().hex) - expires = time() + self.token_life - groups = self._get_user_groups(account, account_user, account_id) - # Save token - memcache_token_key = '%s/token/%s' % (self.reseller_prefix, token) - memcache_client.set(memcache_token_key, (expires, groups), - time=float(expires - time())) - # Record the token with the user info for future use. - memcache_user_key = \ - '%s/user/%s' % (self.reseller_prefix, account_user) - memcache_client.set(memcache_user_key, token, - time=float(expires - time())) + try: + token, expires = self._create_new_token( + memcache_client, account, account_user, account_id) + except MemcacheConnectionError: + return HTTPServiceUnavailable(request=req) resp = Response(request=req, headers={ 'x-auth-token': token, 'x-storage-token': token, 'x-auth-token-expires': str(int(expires - time()))}) diff --git a/test/unit/common/middleware/test_tempauth.py b/test/unit/common/middleware/test_tempauth.py index a9820de8e6..9e5a50c893 100644 --- a/test/unit/common/middleware/test_tempauth.py +++ b/test/unit/common/middleware/test_tempauth.py @@ -627,6 +627,15 @@ class TestAuth(unittest.TestCase): auth.DEFAULT_TOKEN_LIFE - 0.5, delta=0.5) self.assertGreater(len(resp.headers['x-auth-token']), 10) + def test_get_token_memcache_error(self): + test_auth = auth.filter_factory({'user_ac_user': 'testing'})(FakeApp()) + req = self._make_request( + '/auth/v1.0', + headers={'X-Auth-User': 'ac:user', 'X-Auth-Key': 'testing'}) + req.environ['swift.cache'] = FakeMemcache(error_on_set=[True]) + resp = req.get_response(test_auth) + self.assertEqual(resp.status_int, 503) + def test_get_token_success_other_auth_prefix(self): test_auth = auth.filter_factory({'user_ac_user': 'testing', 'auth_prefix': '/other/'})(FakeApp())