diff --git a/swauth/middleware.py b/swauth/middleware.py index db54467..affc02b 100644 --- a/swauth/middleware.py +++ b/swauth/middleware.py @@ -19,6 +19,7 @@ import hmac from httplib import HTTPConnection from httplib import HTTPSConnection import json +import swift from time import gmtime from time import strftime from time import time @@ -58,7 +59,7 @@ import swauth.authtypes from swauth import swift_version -MEMCACHE_TIME = swift_version.newer_than('1.7.7-dev') +SWIFT_MIN_VERSION = "2.2.0" class Swauth(object): @@ -73,6 +74,14 @@ class Swauth(object): self.app = app self.conf = conf self.logger = get_logger(conf, log_route='swauth') + if not swift_version.at_least(SWIFT_MIN_VERSION): + msg = ("Your Swift installation is too old (%s). You need at " + "least %s." % (swift.__version__, SWIFT_MIN_VERSION)) + try: + self.logger.critical(msg) + except Exception: + pass + raise ValueError(msg) self.log_headers = conf.get('log_headers', 'no').lower() in TRUE_VALUES self.reseller_prefix = conf.get('reseller_prefix', 'AUTH').strip() if self.reseller_prefix and self.reseller_prefix[-1] != '_': @@ -361,14 +370,9 @@ class Swauth(object): expires_from_now = float(resp.getheader('x-auth-ttl')) groups = resp.getheader('x-auth-groups') if memcache_client: - if MEMCACHE_TIME: - memcache_client.set( - memcache_key, (time() + expires_from_now, groups), - time=expires_from_now) - else: - memcache_client.set( - memcache_key, (time() + expires_from_now, groups), - timeout=expires_from_now) + memcache_client.set( + memcache_key, (time() + expires_from_now, groups), + time=expires_from_now) else: path = quote('/v1/%s/.token_%s/%s' % (self.auth_account, token[-1], token)) @@ -387,16 +391,10 @@ class Swauth(object): groups.append(detail['account_id']) groups = ','.join(groups) if memcache_client: - if MEMCACHE_TIME: - memcache_client.set( - memcache_key, - (detail['expires'], groups), - time=float(detail['expires'] - time())) - else: - memcache_client.set( - memcache_key, - (detail['expires'], groups), - timeout=float(detail['expires'] - time())) + memcache_client.set( + memcache_key, + (detail['expires'], groups), + time=float(detail['expires'] - time())) return groups def authorize(self, req): @@ -1449,18 +1447,11 @@ class Swauth(object): if not memcache_client: raise Exception( 'No memcache set up; required for Swauth middleware') - if MEMCACHE_TIME: - memcache_client.set( - memcache_key, - (self.itoken_expires, - '.auth,.reseller_admin,%s.auth' % self.reseller_prefix), - time=self.token_life) - else: - memcache_client.set( - memcache_key, - (self.itoken_expires, - '.auth,.reseller_admin,%s.auth' % self.reseller_prefix), - timeout=self.token_life) + memcache_client.set( + memcache_key, + (self.itoken_expires, + '.auth,.reseller_admin,%s.auth' % self.reseller_prefix), + time=self.token_life) return self.itoken def get_admin_detail(self, req): diff --git a/swauth/swift_version.py b/swauth/swift_version.py index fa524f3..dd96f97 100644 --- a/swauth/swift_version.py +++ b/swauth/swift_version.py @@ -57,3 +57,26 @@ def newer_than(value): # Unable to detect if it's newer, better to fail return False return True + + +def at_least(value): + global MAJOR, MINOR, REVISION, FINAL + try: + major, minor, revision, final = parse(value) + if MAJOR is None: + MAJOR, MINOR, REVISION, FINAL = parse(swift.__version__) + if MAJOR < major: + return False + elif MAJOR == major: + if MINOR < minor: + return False + elif MINOR == minor: + if REVISION < revision: + return False + elif REVISION == revision: + if not FINAL and final: + return False + except Exception: + # Unable to detect if it's newer, better to fail + return False + return True diff --git a/test/unit/test_middleware.py b/test/unit/test_middleware.py index d04dd82..9c93060 100644 --- a/test/unit/test_middleware.py +++ b/test/unit/test_middleware.py @@ -15,6 +15,7 @@ from contextlib import contextmanager import json +import mock from time import time import unittest @@ -37,16 +38,16 @@ class FakeMemcache(object): def get(self, key): return self.store.get(key) - def set(self, key, value, timeout=0, time=0): + def set(self, key, value, time=0): self.store[key] = value return True - def incr(self, key, timeout=0, time=0): + def incr(self, key, time=0): self.store[key] = self.store.setdefault(key, 0) + 1 return self.store[key] @contextmanager - def soft_lock(self, key, timeout=0, retries=5, time=0): + def soft_lock(self, key, retries=5, time=0): yield True def delete(self, key): @@ -117,6 +118,13 @@ class TestAuth(unittest.TestCase): 'token_life': str(DEFAULT_TOKEN_LIFE), 'max_token_life': str(MAX_TOKEN_LIFE)})(FakeApp()) + def test_swift_version(self): + app = FakeApp() + + with mock.patch('swauth.swift_version.at_least') as mock_at_least: + mock_at_least.return_value = False + self.assertRaises(ValueError, auth.filter_factory({}), app) + def test_super_admin_key_not_required(self): auth.filter_factory({})(FakeApp()) diff --git a/test/unit/test_swift_version.py b/test/unit/test_swift_version.py index 1576ea2..5fe278b 100644 --- a/test/unit/test_swift_version.py +++ b/test/unit/test_swift_version.py @@ -105,3 +105,80 @@ class TestSwiftVersion(unittest.TestCase): self.assertFalse(ver.newer_than('2.0')) swift.__version__ = orig_version + + def test_at_least(self): + orig_version = swift.__version__ + + swift.__version__ = '1.3' + ver.MAJOR = None + self.assertTrue(ver.at_least('1.2')) + self.assertTrue(ver.at_least('1.2.9')) + self.assertTrue(ver.at_least('1.3-dev')) + self.assertTrue(ver.at_least('1.3.0-dev')) + self.assertTrue(ver.at_least('1.3')) + self.assertTrue(ver.at_least('1.3.0')) + self.assertFalse(ver.at_least('1.3.1-dev')) + self.assertFalse(ver.at_least('1.3.1')) + self.assertFalse(ver.at_least('1.4-dev')) + self.assertFalse(ver.at_least('1.4')) + self.assertFalse(ver.at_least('2.0-dev')) + self.assertFalse(ver.at_least('2.0')) + + swift.__version__ = '1.3-dev' + ver.MAJOR = None + self.assertTrue(ver.at_least('1.2')) + self.assertTrue(ver.at_least('1.2.9')) + self.assertTrue(ver.at_least('1.3-dev')) + self.assertTrue(ver.at_least('1.3.0-dev')) + self.assertFalse(ver.at_least('1.3')) + self.assertFalse(ver.at_least('1.3.0')) + self.assertFalse(ver.at_least('1.3.1-dev')) + self.assertFalse(ver.at_least('1.3.1')) + self.assertFalse(ver.at_least('1.4-dev')) + self.assertFalse(ver.at_least('1.4')) + self.assertFalse(ver.at_least('2.0-dev')) + self.assertFalse(ver.at_least('2.0')) + + swift.__version__ = '1.5.6' + ver.MAJOR = None + self.assertTrue(ver.at_least('1.4')) + self.assertTrue(ver.at_least('1.5')) + self.assertTrue(ver.at_least('1.5.5-dev')) + self.assertTrue(ver.at_least('1.5.5')) + self.assertTrue(ver.at_least('1.5.6-dev')) + self.assertTrue(ver.at_least('1.5.6')) + self.assertFalse(ver.at_least('1.5.7-dev')) + self.assertFalse(ver.at_least('1.5.7')) + self.assertFalse(ver.at_least('1.6-dev')) + self.assertFalse(ver.at_least('1.6')) + self.assertFalse(ver.at_least('2.0-dev')) + self.assertFalse(ver.at_least('2.0')) + + swift.__version__ = '1.5.6-dev' + ver.MAJOR = None + self.assertTrue(ver.at_least('1.4')) + self.assertTrue(ver.at_least('1.5')) + self.assertTrue(ver.at_least('1.5.5-dev')) + self.assertTrue(ver.at_least('1.5.5')) + self.assertTrue(ver.at_least('1.5.6-dev')) + self.assertFalse(ver.at_least('1.5.6')) + self.assertFalse(ver.at_least('1.5.7-dev')) + self.assertFalse(ver.at_least('1.5.7')) + self.assertFalse(ver.at_least('1.6-dev')) + self.assertFalse(ver.at_least('1.6')) + self.assertFalse(ver.at_least('2.0-dev')) + self.assertFalse(ver.at_least('2.0')) + + swift.__version__ = '1.10.0-2.el6' + ver.MAJOR = None + self.assertTrue(ver.at_least('1.9')) + self.assertTrue(ver.at_least('1.10.0-dev')) + self.assertTrue(ver.at_least('1.10.0')) + self.assertFalse(ver.at_least('1.11')) + self.assertFalse(ver.at_least('2.0')) + + swift.__version__ = 'garbage' + ver.MAJOR = None + self.assertFalse(ver.at_least('2.0')) + + swift.__version__ = orig_version