commit 93724532f0903d733436ca311844e1c193fc63d0 Author: Samuel Merritt Date: Tue Apr 28 14:13:30 2015 -0700 Better scoping for tempurls, especially container tempurls It used to be that a GET of a tempurl referencing a large object would let you download that large object regardless of where its segments lived. However, this led to some violated user expectations around container tempurls. (Note on shorthand: all tempurls reference objects. However, "account tempurl" and "container tempurl" are shorthand meaning tempurls generated using a key on the account or container, respectively.) Let's say an application is given tempurl keys to a particular container, and it does all its work therein using those keys. The user expects that, if the application is compromised, then the attacker only gains access to that particular container. However, with the old behavior, the attacker could read data from any container like so: 1) Choose a victim container to download 2) Create PUT and GET tempurl for any object name within the container. The object doesn't need to exist; we'll create it. 3) Using the PUT tempurl, upload a DLO manifest with "X-Object-Manifest: /victim-container/" 4) Using the GET tempurl, download the object created in step 3. The result will be the concatenation of all objects in the victim container. Step 3 need not be for all objects in the container; for example, a value "X-Object-Manifest: /victim-container/abc" would only be the concatenation of all objects whose names begin with "abc". By probing for object names in this way, individual objects may be found and extracted. A similar bug would exist for manifests referencing other accounts except that neither the X-Object-Manifest (DLO) nor the JSON manifest document (SLO) have a way of specifying a different account. This change makes it so that a container tempurl only grants access to objects within its container, *including* large-object segments. This breaks backward compatibility for container tempurls, but (a) there are security implications, and (b) container tempurls are a new feature not yet in any named OpenStack release, so we can get away with it. This works by having the tempurl middleware install an authorization callback ('swift.authorize' in the WSGI environment) that limits the scope of any requests to the account or container from which the key came. This required a small change to how get_*_info() results are cached in the WSGI environment; each result used to be a top-level key in the environment, but now they are in a sub-dictionary. For example, env['swift.container/a/c'] is now env['swift.infocache']['swift.container/a/c']. This lets us shallow-copy the environment without breaking the caching. This is extra-important since the get_*_info() functions work by making a request, then reaching into the response's environ dict and pulling things out from there. If you fail to preserve the identity of the environment from request through to response, then you break get_*_info(). With this change, you only need to preserve the identity of environ['swift.infocache']; the rest can be copied and modified at will. This allows the proxy to remove environ['swift.authorize'] from a copy of the request without (a) disturbing the info cache, or (b) removing environ['swift.authorize'] from every subsequent request made by the dlo middleware. Change-Id: Iab900270713b649434a11cb3b8bc58c2e8c5c076 diff --git a/swift/common/middleware/tempurl.py b/swift/common/middleware/tempurl.py index 3dd1448..6767563 100644 --- a/swift/common/middleware/tempurl.py +++ b/swift/common/middleware/tempurl.py @@ -150,6 +150,10 @@ DEFAULT_OUTGOING_REMOVE_HEADERS = 'x-object-meta-*' DEFAULT_OUTGOING_ALLOW_HEADERS = 'x-object-meta-public-*' +CONTAINER_SCOPE = 'container' +ACCOUNT_SCOPE = 'account' + + def get_tempurl_keys_from_metadata(meta): """ Extracts the tempurl keys from metadata. @@ -170,6 +174,38 @@ def disposition_format(filename): quote(filename, safe=' /'), quote(filename)) +def authorize_same_account(account_to_match): + + def auth_callback_same_account(req): + try: + _ver, acc, _rest = req.split_path(2, 3, True) + except ValueError: + return None + + if acc == account_to_match: + return None + else: + return HTTPUnauthorized(request=req) + + return auth_callback_same_account + + +def authorize_same_container(account_to_match, container_to_match): + + def auth_callback_same_container(req): + try: + _ver, acc, con, _rest = req.split_path(3, 4, True) + except ValueError: + return None + + if acc == account_to_match and con == container_to_match: + return None + else: + return HTTPUnauthorized(request=req) + + return auth_callback_same_container + + class TempURL(object): """ WSGI Middleware to grant temporary URLs specific access to Swift @@ -298,10 +334,10 @@ class TempURL(object): return self.app(env, start_response) if not temp_url_sig or not temp_url_expires: return self._invalid(env, start_response) - account = self._get_account(env) + account, container = self._get_account_and_container(env) if not account: return self._invalid(env, start_response) - keys = self._get_keys(env, account) + keys = self._get_keys(env) if not keys: return self._invalid(env, start_response) if env['REQUEST_METHOD'] == 'HEAD': @@ -316,15 +352,25 @@ class TempURL(object): else: hmac_vals = self._get_hmacs(env, temp_url_expires, keys) - # While it's true that any() will short-circuit, this doesn't affect - # the timing-attack resistance since the only way this will - # short-circuit is when a valid signature is passed in. - is_valid_hmac = any(streq_const_time(temp_url_sig, hmac) - for hmac in hmac_vals) + is_valid_hmac = False + hmac_scope = None + for hmac, scope in hmac_vals: + # While it's true that we short-circuit, this doesn't affect the + # timing-attack resistance since the only way this will + # short-circuit is when a valid signature is passed in. + if streq_const_time(temp_url_sig, hmac): + is_valid_hmac = True + hmac_scope = scope + break if not is_valid_hmac: return self._invalid(env, start_response) self._clean_incoming_headers(env) - env['swift.authorize'] = lambda req: None + + if hmac_scope == ACCOUNT_SCOPE: + env['swift.authorize'] = authorize_same_account(account) + else: + env['swift.authorize'] = authorize_same_container(account, + container) env['swift.authorize_override'] = True env['REMOTE_USER'] = '.wsgi.tempurl' qs = {'temp_url_sig': temp_url_sig, @@ -365,22 +411,23 @@ class TempURL(object): return self.app(env, _start_response) - def _get_account(self, env): + def _get_account_and_container(self, env): """ - Returns just the account for the request, if it's an object - request and one of the configured methods; otherwise, None is + Returns just the account and container for the request, if it's an + object request and one of the configured methods; otherwise, None is returned. :param env: The WSGI environment for the request. - :returns: Account str or None. + :returns: (Account str, container str) or (None, None). """ if env['REQUEST_METHOD'] in self.methods: try: ver, acc, cont, obj = split_path(env['PATH_INFO'], 4, 4, True) except ValueError: - return None + return (None, None) if ver == 'v1' and obj.strip('/'): - return acc + return (acc, cont) + return (None, None) def _get_temp_url_info(self, env): """ @@ -410,18 +457,23 @@ class TempURL(object): inline = True return temp_url_sig, temp_url_expires, filename, inline - def _get_keys(self, env, account): + def _get_keys(self, env): """ Returns the X-[Account|Container]-Meta-Temp-URL-Key[-2] header values - for the account or container, or an empty list if none are set. + for the account or container, or an empty list if none are set. Each + value comes as a 2-tuple (key, scope), where scope is either + CONTAINER_SCOPE or ACCOUNT_SCOPE. Returns 0-4 elements depending on how many keys are set in the account's or container's metadata. :param env: The WSGI environment for the request. - :param account: Account str. - :returns: [X-Account-Meta-Temp-URL-Key str value if set, - X-Account-Meta-Temp-URL-Key-2 str value if set] + :returns: [ + (X-Account-Meta-Temp-URL-Key str value, ACCOUNT_SCOPE) if set, + (X-Account-Meta-Temp-URL-Key-2 str value, ACCOUNT_SCOPE if set, + (X-Container-Meta-Temp-URL-Key str value, CONTAINER_SCOPE) if set, + (X-Container-Meta-Temp-URL-Key-2 str value, CONTAINER_SCOPE if set, + ] """ account_info = get_account_info(env, self.app, swift_source='TU') account_keys = get_tempurl_keys_from_metadata(account_info['meta']) @@ -430,25 +482,28 @@ class TempURL(object): container_keys = get_tempurl_keys_from_metadata( container_info.get('meta', [])) - return account_keys + container_keys + return ([(ak, ACCOUNT_SCOPE) for ak in account_keys] + + [(ck, CONTAINER_SCOPE) for ck in container_keys]) - def _get_hmacs(self, env, expires, keys, request_method=None): + def _get_hmacs(self, env, expires, scoped_keys, request_method=None): """ :param env: The WSGI environment for the request. :param expires: Unix timestamp as an int for when the URL expires. - :param keys: Key strings, from the X-Account-Meta-Temp-URL-Key[-2] of - the account. + :param scoped_keys: (key, scope) tuples like _get_keys() returns :param request_method: Optional override of the request in the WSGI env. For example, if a HEAD does not match, you may wish to override with GET to still allow the HEAD. + + :returns: a list of (hmac, scope) 2-tuples """ if not request_method: request_method = env['REQUEST_METHOD'] - return [get_hmac( - request_method, env['PATH_INFO'], expires, key) for key in keys] + return [ + (get_hmac(request_method, env['PATH_INFO'], expires, key), scope) + for (key, scope) in scoped_keys] def _invalid(self, env, start_response): """ diff --git a/swift/proxy/controllers/base.py b/swift/proxy/controllers/base.py index 6bf7ea0..5588cb5 100644 --- a/swift/proxy/controllers/base.py +++ b/swift/proxy/controllers/base.py @@ -377,6 +377,7 @@ def _set_info_cache(app, env, account, container, resp): :param container: the unquoted container name or None :param resp: the response received or None if info cache should be cleared """ + infocache = env.setdefault('swift.infocache', {}) if container: cache_time = app.recheck_container_existence @@ -395,7 +396,7 @@ def _set_info_cache(app, env, account, container, resp): # Next actually set both memcache and the env cache memcache = getattr(app, 'memcache', None) or env.get('swift.cache') if not cache_time: - env.pop(env_key, None) + infocache.pop(env_key, None) if memcache: memcache.delete(cache_key) return @@ -406,7 +407,7 @@ def _set_info_cache(app, env, account, container, resp): info = headers_to_account_info(resp.headers, resp.status_int) if memcache: memcache.set(cache_key, info, time=cache_time) - env[env_key] = info + infocache[env_key] = info def _set_object_info_cache(app, env, account, container, obj, resp): @@ -429,12 +430,12 @@ def _set_object_info_cache(app, env, account, container, obj, resp): env_key = get_object_env_key(account, container, obj) - if not resp: - env.pop(env_key, None) + if 'swift.infocache' in env and not resp: + env['swift.infocache'].pop(env_key, None) return info = headers_to_object_info(resp.headers, resp.status_int) - env[env_key] = info + env.setdefault('swift.infocache', {})[env_key] = info def clear_info_cache(app, env, account, container=None): @@ -460,8 +461,8 @@ def _get_info_cache(app, env, account, container=None): """ cache_key, env_key = _get_cache_key(account, container) - if env_key in env: - return env[env_key] + if 'swift.infocache' in env and env_key in env['swift.infocache']: + return env['swift.infocache'][env_key] memcache = getattr(app, 'memcache', None) or env.get('swift.cache') if memcache: info = memcache.get(cache_key) @@ -469,7 +470,7 @@ def _get_info_cache(app, env, account, container=None): for key in info: if isinstance(info[key], unicode): info[key] = info[key].encode("utf-8") - env[env_key] = info + env.setdefault('swift.infocache', {})[env_key] = info return info return None @@ -523,14 +524,15 @@ def get_info(app, env, account, container=None, ret_not_found=False, req = _prepare_pre_auth_info_request( env, path, (swift_source or 'GET_INFO')) - # Whenever we do a GET/HEAD, the GETorHEAD_base will set the info in - # the environment under environ[env_key] and in memcache. We will - # pick the one from environ[env_key] and use it to set the caller env + # Whenever we do a GET/HEAD, the GETorHEAD_base will set the info in the + # environment under environ['swift.infocache'][env_key] and in memcache. + # We will pick the one from environ['swift.infocache'][env_key] and use + # it to set the caller env resp = req.get_response(app) cache_key, env_key = _get_cache_key(account, container) try: - info = resp.environ[env_key] - env[env_key] = info + info = resp.environ['swift.infocache'][env_key] + env.setdefault('swift.infocache', {})[env_key] = info if ret_not_found or is_success(info['status']): return info except (KeyError, AttributeError): @@ -553,7 +555,7 @@ def _get_object_info(app, env, account, container, obj, swift_source=None): :returns: the cached info or None if cannot be retrieved """ env_key = get_object_env_key(account, container, obj) - info = env.get(env_key) + info = env.get('swift.infocache', {}).get(env_key) if info: return info # Not in cached, let's try the object servers @@ -564,8 +566,8 @@ def _get_object_info(app, env, account, container, obj, swift_source=None): # pick the one from environ[env_key] and use it to set the caller env resp = req.get_response(app) try: - info = resp.environ[env_key] - env[env_key] = info + info = resp.environ['swift.infocache'][env_key] + env.setdefault('swift.infocache', {})[env_key] = info return info except (KeyError, AttributeError): pass diff --git a/swift/proxy/server.py b/swift/proxy/server.py index b631542..39d3ac9 100644 --- a/swift/proxy/server.py +++ b/swift/proxy/server.py @@ -388,6 +388,8 @@ class Application(object): if not resp and not req.headers.get('X-Copy-From-Account') \ and not req.headers.get('Destination-Account'): # No resp means authorized, no delayed recheck required. + req.environ.setdefault('swift.infocache', {}) + req = Request(req.environ.copy()) del req.environ['swift.authorize'] else: # Response indicates denial, but we might delay the denial diff --git a/test/functional/tests.py b/test/functional/tests.py index 95f168e..bae479c 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -2898,6 +2898,57 @@ class TestContainerTempurl(Base): contents = self.env.obj.read(parms=parms, cfg={'no_auth_token': True}) self.assertEqual(contents, "obj contents") + def test_GET_DLO_inside_container(self): + seg1 = self.env.container.file( + "get-dlo-inside-seg1" + Utils.create_name()) + seg2 = self.env.container.file( + "get-dlo-inside-seg2" + Utils.create_name()) + seg1.write("one fish two fish ") + seg2.write("red fish blue fish") + + manifest = self.env.container.file("manifest" + Utils.create_name()) + manifest.write( + '', + hdrs={"X-Object-Manifest": "%s/get-dlo-inside-seg" % + (self.env.container.name,)}) + + expires = int(time.time()) + 86400 + sig = self.tempurl_sig( + 'GET', expires, self.env.conn.make_path(manifest.path), + self.env.tempurl_key) + parms = {'temp_url_sig': sig, + 'temp_url_expires': str(expires)} + + contents = manifest.read(parms=parms, cfg={'no_auth_token': True}) + self.assertEqual(contents, "one fish two fish red fish blue fish") + + def test_GET_DLO_outside_container(self): + seg1 = self.env.container.file( + "get-dlo-outside-seg1" + Utils.create_name()) + seg2 = self.env.container.file( + "get-dlo-outside-seg2" + Utils.create_name()) + seg1.write("one fish two fish ") + seg2.write("red fish blue fish") + + container2 = self.env.account.container(Utils.create_name()) + + manifest = self.env.container.file("manifest" + Utils.create_name()) + manifest.write( + '', + hdrs={"X-Object-Manifest": "%s/get-dlo-outside-seg" % + (container2.name,)}) + + expires = int(time.time()) + 86400 + sig = self.tempurl_sig( + 'GET', expires, self.env.conn.make_path(manifest.path), + self.env.tempurl_key) + parms = {'temp_url_sig': sig, + 'temp_url_expires': str(expires)} + + self.assertRaises(ResponseError, manifest.read, + parms=parms, cfg={'no_auth_token': True}) + self.assert_status([401]) + def test_PUT(self): new_obj = self.env.container.file(Utils.create_name()) diff --git a/test/unit/common/middleware/test_account_quotas.py b/test/unit/common/middleware/test_account_quotas.py index e8c2563..96485a5 100644 --- a/test/unit/common/middleware/test_account_quotas.py +++ b/test/unit/common/middleware/test_account_quotas.py @@ -58,7 +58,8 @@ class FakeApp(object): if env['REQUEST_METHOD'] == "HEAD" and \ env['PATH_INFO'] == '/v1/a/c2/o2': env_key = get_object_env_key('a', 'c2', 'o2') - env[env_key] = headers_to_object_info(self.headers, 200) + env.setdefault('swift.infocache', {})[env_key] = \ + headers_to_object_info(self.headers, 200) start_response('200 OK', self.headers) elif env['REQUEST_METHOD'] == "HEAD" and \ env['PATH_INFO'] == '/v1/a/c2/o3': @@ -66,7 +67,8 @@ class FakeApp(object): else: # Cache the account_info (same as a real application) cache_key, env_key = _get_cache_key('a', None) - env[env_key] = headers_to_account_info(self.headers, 200) + env.setdefault('swift.infocache', {})[env_key] = \ + headers_to_account_info(self.headers, 200) start_response('200 OK', self.headers) return [] diff --git a/test/unit/common/middleware/test_container_sync.py b/test/unit/common/middleware/test_container_sync.py index 8ef4ad6..d4787d6 100644 --- a/test/unit/common/middleware/test_container_sync.py +++ b/test/unit/common/middleware/test_container_sync.py @@ -202,7 +202,8 @@ cluster_dfw1 = http://dfw1.host/v1/ def test_invalid_sig(self): req = swob.Request.blank( '/v1/a/c', headers={'x-container-sync-auth': 'US nonce sig'}) - req.environ[_get_cache_key('a', 'c')[1]] = {'sync_key': 'abc'} + infocache = req.environ.setdefault('swift.infocache', {}) + infocache[_get_cache_key('a', 'c')[1]] = {'sync_key': 'abc'} resp = req.get_response(self.sync) self.assertEqual(resp.status, '401 Unauthorized') self.assertEqual( @@ -219,7 +220,8 @@ cluster_dfw1 = http://dfw1.host/v1/ self.sync.realms_conf.key('US'), 'abc') req = swob.Request.blank( '/v1/a/c', headers={'x-container-sync-auth': 'US nonce ' + sig}) - req.environ[_get_cache_key('a', 'c')[1]] = {'sync_key': 'abc'} + infocache = req.environ.setdefault('swift.infocache', {}) + infocache[_get_cache_key('a', 'c')[1]] = {'sync_key': 'abc'} resp = req.get_response(self.sync) self.assertEqual(resp.status, '200 OK') self.assertEqual(resp.body, 'Response to Authorized Request') @@ -233,7 +235,8 @@ cluster_dfw1 = http://dfw1.host/v1/ self.sync.realms_conf.key2('US'), 'abc') req = swob.Request.blank( '/v1/a/c', headers={'x-container-sync-auth': 'US nonce ' + sig}) - req.environ[_get_cache_key('a', 'c')[1]] = {'sync_key': 'abc'} + infocache = req.environ.setdefault('swift.infocache', {}) + infocache[_get_cache_key('a', 'c')[1]] = {'sync_key': 'abc'} resp = req.get_response(self.sync) self.assertEqual(resp.status, '200 OK') self.assertEqual(resp.body, 'Response to Authorized Request') diff --git a/test/unit/common/middleware/test_formpost.py b/test/unit/common/middleware/test_formpost.py index c71eb7c..118207e 100644 --- a/test/unit/common/middleware/test_formpost.py +++ b/test/unit/common/middleware/test_formpost.py @@ -127,8 +127,9 @@ class TestFormPost(unittest.TestCase): meta[meta_name] = key _junk, account, _junk, _junk = split_path(path, 2, 4) - req.environ['swift.account/' + account] = self._fake_cache_env( - account, tempurl_keys) + req.environ.setdefault('swift.infocache', {}) + req.environ['swift.infocache']['swift.account/' + account] = \ + self._fake_cache_env(account, tempurl_keys) return req def _fake_cache_env(self, account, tempurl_keys=()): @@ -216,6 +217,7 @@ class TestFormPost(unittest.TestCase): 'SERVER_NAME': '172.16.83.128', 'SERVER_PORT': '8080', 'SERVER_PROTOCOL': 'HTTP/1.0', + 'swift.infocache': {}, 'wsgi.errors': wsgi_errors, 'wsgi.multiprocess': False, 'wsgi.multithread': True, @@ -242,8 +244,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() - 10), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -343,9 +345,10 @@ class TestFormPost(unittest.TestCase): 'SERVER_NAME': '172.16.83.128', 'SERVER_PORT': '8080', 'SERVER_PROTOCOL': 'HTTP/1.0', - 'swift.account/AUTH_test': self._fake_cache_env( - 'AUTH_test', [key]), - 'swift.container/AUTH_test/container': {'meta': {}}, + 'swift.infocache': { + 'swift.account/AUTH_test': self._fake_cache_env( + 'AUTH_test', [key]), + 'swift.container/AUTH_test/container': {'meta': {}}}, 'wsgi.errors': wsgi_errors, 'wsgi.input': wsgi_input, 'wsgi.multiprocess': False, @@ -456,9 +459,10 @@ class TestFormPost(unittest.TestCase): 'SERVER_NAME': '172.16.83.128', 'SERVER_PORT': '8080', 'SERVER_PROTOCOL': 'HTTP/1.0', - 'swift.account/AUTH_test': self._fake_cache_env( - 'AUTH_test', [key]), - 'swift.container/AUTH_test/container': {'meta': {}}, + 'swift.infocache': { + 'swift.account/AUTH_test': self._fake_cache_env( + 'AUTH_test', [key]), + 'swift.container/AUTH_test/container': {'meta': {}}}, 'wsgi.errors': wsgi_errors, 'wsgi.input': wsgi_input, 'wsgi.multiprocess': False, @@ -572,9 +576,10 @@ class TestFormPost(unittest.TestCase): 'SERVER_NAME': '172.16.83.128', 'SERVER_PORT': '8080', 'SERVER_PROTOCOL': 'HTTP/1.0', - 'swift.account/AUTH_test': self._fake_cache_env( - 'AUTH_test', [key]), - 'swift.container/AUTH_test/container': {'meta': {}}, + 'swift.infocache': { + 'swift.account/AUTH_test': self._fake_cache_env( + 'AUTH_test', [key]), + 'swift.container/AUTH_test/container': {'meta': {}}}, 'wsgi.errors': wsgi_errors, 'wsgi.input': wsgi_input, 'wsgi.multiprocess': False, @@ -684,9 +689,10 @@ class TestFormPost(unittest.TestCase): 'SERVER_NAME': '172.16.83.128', 'SERVER_PORT': '8080', 'SERVER_PROTOCOL': 'HTTP/1.0', - 'swift.account/AUTH_test': self._fake_cache_env( - 'AUTH_test', [key]), - 'swift.container/AUTH_test/container': {'meta': {}}, + 'swift.infocache': { + 'swift.account/AUTH_test': self._fake_cache_env( + 'AUTH_test', [key]), + 'swift.container/AUTH_test/container': {'meta': {}}}, 'wsgi.errors': wsgi_errors, 'wsgi.input': wsgi_input, 'wsgi.multiprocess': False, @@ -730,9 +736,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://brim.net', 5, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('XX' + '\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -766,9 +773,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://brim.net', 5, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -797,9 +805,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://brim.net', 1024, 1, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -838,9 +847,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['QUERY_STRING'] = 'this=should¬=get&passed' env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp( iter([('201 Created', {}, ''), ('201 Created', {}, '')]), @@ -873,9 +883,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://brim.net', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('404 Not Found', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -956,9 +967,10 @@ class TestFormPost(unittest.TestCase): '------WebKitFormBoundaryNcxTqxSlX7t4TDkR--', '', ])) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1024,9 +1036,10 @@ class TestFormPost(unittest.TestCase): '------WebKitFormBoundaryNcxTqxSlX7t4TDkR--', '', ])) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1064,9 +1077,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://redirect', 1024, 10, int(time() + 86400), key, user_agent=False) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1085,9 +1099,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://redirect', 1024, 10, int(time() + 86400), key, user_agent=False) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} env['HTTP_ORIGIN'] = 'http://localhost:5000' self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', @@ -1114,9 +1129,10 @@ class TestFormPost(unittest.TestCase): int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) # Stick it in X-Account-Meta-Temp-URL-Key-2 and make sure we get it - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', ['bert', key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', ['bert', key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1150,9 +1166,11 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://redirect', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env('AUTH_test') + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test') # Stick it in X-Container-Meta-Temp-URL-Key-2 and ensure we get it - env['swift.container/AUTH_test/container'] = {'meta': meta} + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': meta} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1176,9 +1194,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://redirect', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1214,9 +1233,10 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', 'http://redirect?one=two', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1252,9 +1272,10 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1289,8 +1310,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() - 10), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1323,8 +1344,8 @@ class TestFormPost(unittest.TestCase): '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) # Change key to invalidate sig - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key + ' is bogus now']) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key + ' is bogus now']) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1356,8 +1377,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('XX' + '\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1389,8 +1410,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v2/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1422,8 +1443,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '//AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1455,8 +1476,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1//container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1488,8 +1509,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_tst/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([ ('200 Ok', {'x-account-meta-temp-url-key': 'def'}, ''), ('201 Created', {}, ''), @@ -1523,8 +1544,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1561,8 +1582,8 @@ class TestFormPost(unittest.TestCase): body[i] = 'badvalue' break env['wsgi.input'] = StringIO('\r\n'.join(body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1601,9 +1622,10 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(x_delete_body_part + body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1643,8 +1665,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(x_delete_body_part + body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1677,9 +1699,10 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(x_delete_body_part + body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) - env['swift.container/AUTH_test/container'] = {'meta': {}} + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) + env['swift.infocache']['swift.container/AUTH_test/container'] = \ + {'meta': {}} self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) @@ -1719,8 +1742,8 @@ class TestFormPost(unittest.TestCase): sig, env, body = self._make_sig_env_body( '/v1/AUTH_test/container', '', 1024, 10, int(time() + 86400), key) env['wsgi.input'] = StringIO('\r\n'.join(x_delete_body_part + body)) - env['swift.account/AUTH_test'] = self._fake_cache_env( - 'AUTH_test', [key]) + env['swift.infocache']['swift.account/AUTH_test'] = \ + self._fake_cache_env('AUTH_test', [key]) self.app = FakeApp(iter([('201 Created', {}, ''), ('201 Created', {}, '')])) self.auth = tempauth.filter_factory({})(self.app) diff --git a/test/unit/common/middleware/test_keystoneauth.py b/test/unit/common/middleware/test_keystoneauth.py index 078c275..9bbaab7 100644 --- a/test/unit/common/middleware/test_keystoneauth.py +++ b/test/unit/common/middleware/test_keystoneauth.py @@ -252,7 +252,7 @@ class SwiftAuth(unittest.TestCase): path = '/v1/' + account # fake cached account info _, info_key = _get_cache_key(account, None) - env = {info_key: {'status': 0, 'sysmeta': {}}, + env = {'swift.infocache': {info_key: {'status': 0, 'sysmeta': {}}}, 'keystone.token_info': _fake_token_info(version='3')} req = Request.blank(path, environ=env, headers=headers) req.method = 'POST' @@ -281,7 +281,7 @@ class SwiftAuth(unittest.TestCase): path = '/v1/' + account # fake cached account info _, info_key = _get_cache_key(account, None) - env = {info_key: {'status': 0, 'sysmeta': {}}, + env = {'swift.infocache': {info_key: {'status': 0, 'sysmeta': {}}}, 'keystone.token_info': _fake_token_info(version='3')} req = Request.blank(path, environ=env, headers=headers) req.method = 'POST' @@ -303,7 +303,7 @@ class SwiftAuth(unittest.TestCase): path = '/v1/' + account _, info_key = _get_cache_key(account, None) # v2 token - env = {info_key: {'status': 0, 'sysmeta': {}}, + env = {'swift.infocache': {info_key: {'status': 0, 'sysmeta': {}}}, 'keystone.token_info': _fake_token_info(version='2')} req = Request.blank(path, environ=env, headers=headers) req.method = 'POST' @@ -325,7 +325,7 @@ class SwiftAuth(unittest.TestCase): path = '/v1/' + account _, info_key = _get_cache_key(account, None) # v2 token - env = {info_key: {'status': 0, 'sysmeta': {}}, + env = {'swift.infocache': {info_key: {'status': 0, 'sysmeta': {}}}, 'keystone.token_info': _fake_token_info(version='2')} req = Request.blank(path, environ=env, headers=headers) req.method = 'POST' @@ -379,7 +379,7 @@ class ServiceTokenFunctionality(unittest.TestCase): service_role=service_role) (version, account, _junk, _junk) = split_path(path, 2, 4, True) _, info_key = _get_cache_key(account, None) - env = {info_key: {'status': 0, 'sysmeta': {}}, + env = {'swift.infocache': {info_key: {'status': 0, 'sysmeta': {}}}, 'keystone.token_info': _fake_token_info(version='2')} req = Request.blank(path, environ=env, headers=headers) req.method = method @@ -564,8 +564,9 @@ class TestAuthorize(BaseTestAuthorize): path = '/v1/%s/c' % account # fake cached account info _, info_key = _get_cache_key(account, None) - default_env = {'REMOTE_USER': identity['HTTP_X_TENANT_ID'], - info_key: {'status': 200, 'sysmeta': {}}} + default_env = { + 'REMOTE_USER': identity['HTTP_X_TENANT_ID'], + 'swift.infocache': {info_key: {'status': 200, 'sysmeta': {}}}} default_env.update(identity) if env: default_env.update(env) @@ -978,7 +979,7 @@ class TestAuthorize(BaseTestAuthorize): info = {'sysmeta': sysmeta} _, info_key = _get_cache_key('AUTH_1234', None) env = {'PATH_INFO': '/v1/AUTH_1234', - info_key: info} + 'swift.infocache': {info_key: info}} # account does not exist info['status'] = 404 @@ -1021,7 +1022,8 @@ class TestIsNameAllowedInACL(BaseTestAuthorize): # pretend account exists info = {'status': 200, 'sysmeta': sysmeta} _, info_key = _get_cache_key(account, None) - req = Request.blank(path, environ={info_key: info}) + req = Request.blank(path, + environ={'swift.infocache': {info_key: info}}) if scoped == 'account': project_name = 'account_name' @@ -1207,7 +1209,7 @@ class TestSetProjectDomain(BaseTestAuthorize): sysmeta['project-domain-id'] = sysmeta_project_domain_id info = {'status': status, 'sysmeta': sysmeta} _, info_key = _get_cache_key(account, None) - env = {info_key: info} + env = {'swift.infocache': {info_key: info}} # create fake env identity env_id = self._get_env_id(tenant_id=req_project_id, diff --git a/test/unit/common/middleware/test_quotas.py b/test/unit/common/middleware/test_quotas.py index 56a7780..08efc74 100644 --- a/test/unit/common/middleware/test_quotas.py +++ b/test/unit/common/middleware/test_quotas.py @@ -100,9 +100,11 @@ class TestContainerQuotas(unittest.TestCase): cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '2'}}) req = Request.blank('/v1/a/c/o', - environ={'REQUEST_METHOD': 'PUT', - 'swift.object/a/c2/o2': {'length': 10}, - 'swift.cache': cache}, + environ={ + 'REQUEST_METHOD': 'PUT', + 'swift.infocache': { + 'swift.object/a/c2/o2': {'length': 10}}, + 'swift.cache': cache}, headers={'x-copy-from': '/c2/o2'}) res = req.get_response(app) self.assertEquals(res.status_int, 413) @@ -113,9 +115,11 @@ class TestContainerQuotas(unittest.TestCase): cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '2'}}) req = Request.blank('/v1/a/c2/o2', - environ={'REQUEST_METHOD': 'COPY', - 'swift.object/a/c2/o2': {'length': 10}, - 'swift.cache': cache}, + environ={ + 'REQUEST_METHOD': 'COPY', + 'swift.infocache': { + 'swift.object/a/c2/o2': {'length': 10}}, + 'swift.cache': cache}, headers={'Destination': '/c/o'}) res = req.get_response(app) self.assertEquals(res.status_int, 413) @@ -135,9 +139,11 @@ class TestContainerQuotas(unittest.TestCase): app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}}) req = Request.blank('/v1/a/c/o', - environ={'REQUEST_METHOD': 'PUT', - 'swift.object/a/c2/o2': {'length': 10}, - 'swift.cache': cache}, + environ={ + 'REQUEST_METHOD': 'PUT', + 'swift.infocache': { + 'swift.object/a/c2/o2': {'length': 10}}, + 'swift.cache': cache}, headers={'x-copy-from': '/c2/o2'}) res = req.get_response(app) self.assertEquals(res.status_int, 200) @@ -146,9 +152,11 @@ class TestContainerQuotas(unittest.TestCase): app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}}) req = Request.blank('/v1/a/c2/o2', - environ={'REQUEST_METHOD': 'COPY', - 'swift.object/a/c2/o2': {'length': 10}, - 'swift.cache': cache}, + environ={ + 'REQUEST_METHOD': 'COPY', + 'swift.infocache': { + 'swift.object/a/c2/o2': {'length': 10}}, + 'swift.cache': cache}, headers={'Destination': '/c/o'}) res = req.get_response(app) self.assertEquals(res.status_int, 200) @@ -157,9 +165,11 @@ class TestContainerQuotas(unittest.TestCase): app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}}) req = Request.blank('/v1/a/c/o', - environ={'REQUEST_METHOD': 'PUT', - 'swift.object/a/c2/o2': {'length': 10}, - 'swift.cache': cache}, + environ={ + 'REQUEST_METHOD': 'PUT', + 'swift.infocache': { + 'swift.object/a/c2/o2': {'length': 10}}, + 'swift.cache': cache}, headers={'x-copy-from': '/c2/o3'}) res = req.get_response(app) self.assertEquals(res.status_int, 200) @@ -178,9 +188,11 @@ class TestContainerQuotas(unittest.TestCase): app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}}) req = Request.blank('/v1/a/c2/o3', - environ={'REQUEST_METHOD': 'COPY', - 'swift.object/a/c2/o2': {'length': 10}, - 'swift.cache': cache}, + environ={ + 'REQUEST_METHOD': 'COPY', + 'swift.infocache': { + 'swift.object/a/c2/o2': {'length': 10}}, + 'swift.cache': cache}, headers={'Destination': '/c/o'}) res = req.get_response(app) self.assertEquals(res.status_int, 200) @@ -200,9 +212,11 @@ class TestContainerQuotas(unittest.TestCase): app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) cache = FakeCache({'object_count': 1, 'meta': {'quota-count': '1'}}) req = Request.blank('/v1/a/c/o', - environ={'REQUEST_METHOD': 'PUT', - 'swift.object/a/c2/o2': {'length': 10}, - 'swift.cache': cache}, + environ={ + 'REQUEST_METHOD': 'PUT', + 'swift.infocache': { + 'swift.object/a/c2/o2': {'length': 10}}, + 'swift.cache': cache}, headers={'x-copy-from': '/c2/o2'}) res = req.get_response(app) self.assertEquals(res.status_int, 413) @@ -227,8 +241,9 @@ class TestContainerQuotas(unittest.TestCase): 'status': 200, 'object_count': 1} req = Request.blank('/v1/a/c2/o2', environ={'REQUEST_METHOD': 'COPY', - 'swift.container/a/c': a_c_cache, - 'swift.container/a2/c': a2_c_cache}, + 'swift.infocache': { + 'swift.container/a/c': a_c_cache, + 'swift.container/a2/c': a2_c_cache}}, headers={'Destination': '/c/o', 'Destination-Account': 'a2'}) res = req.get_response(app) @@ -243,8 +258,9 @@ class TestContainerQuotas(unittest.TestCase): 'status': 200, 'object_count': 1} req = Request.blank('/v1/a2/c/o', environ={'REQUEST_METHOD': 'PUT', - 'swift.container/a/c': a_c_cache, - 'swift.container/a2/c': a2_c_cache}, + 'swift.infocache': { + 'swift.container/a/c': a_c_cache, + 'swift.container/a2/c': a2_c_cache}}, headers={'X-Copy-From': '/c2/o2', 'X-Copy-From-Account': 'a'}) res = req.get_response(app) diff --git a/test/unit/common/middleware/test_tempurl.py b/test/unit/common/middleware/test_tempurl.py index e665563..9c8eefa 100644 --- a/test/unit/common/middleware/test_tempurl.py +++ b/test/unit/common/middleware/test_tempurl.py @@ -29,6 +29,7 @@ # limitations under the License. import hmac +import itertools import unittest from hashlib import sha1 from time import time @@ -44,10 +45,13 @@ class FakeApp(object): self.calls = 0 self.status_headers_body_iter = status_headers_body_iter if not self.status_headers_body_iter: - self.status_headers_body_iter = iter([('404 Not Found', { - 'x-test-header-one-a': 'value1', - 'x-test-header-two-a': 'value2', - 'x-test-header-two-b': 'value3'}, '')]) + self.status_headers_body_iter = iter( + itertools.repeat(( + '404 Not Found', { + 'x-test-header-one-a': 'value1', + 'x-test-header-two-a': 'value2', + 'x-test-header-two-b': 'value3'}, + ''))) self.request = None def __call__(self, env, start_response): @@ -89,7 +93,8 @@ class TestTempURL(unittest.TestCase): if key: meta[meta_name] = key - environ['swift.account/' + account] = { + environ.setdefault('swift.infocache', {}) + environ['swift.infocache']['swift.account/' + account] = { 'status': 204, 'container_count': '0', 'total_object_count': '0', @@ -97,7 +102,8 @@ class TestTempURL(unittest.TestCase): 'meta': meta} container_cache_key = 'swift.container/' + account + '/c' - environ.setdefault(container_cache_key, {'meta': {}}) + environ['swift.infocache'].setdefault(container_cache_key, + {'meta': {}}) def test_passthrough(self): resp = self._make_request('/v1/a/c/o').get_response(self.tempurl) @@ -147,7 +153,7 @@ class TestTempURL(unittest.TestCase): self.assert_valid_sig(expires, path, [key1, key2], sig) def test_get_valid_container_keys(self): - environ = {} + environ = {'swift.infocache': {}} # Add two static container keys container_keys = ['me', 'other'] meta = {} @@ -155,7 +161,7 @@ class TestTempURL(unittest.TestCase): meta_name = 'Temp-URL-key' + (("-%d" % (idx + 1) if idx else "")) if key: meta[meta_name] = key - environ['swift.container/a/c'] = {'meta': meta} + environ['swift.infocache']['swift.container/a/c'] = {'meta': meta} method = 'GET' expires = int(time() + 86400) @@ -581,6 +587,93 @@ class TestTempURL(unittest.TestCase): self.assertTrue('Temp URL invalid' in resp.body) self.assertTrue('Www-Authenticate' in resp.headers) + def test_authorize_limits_scope(self): + environ = { + 'swift.infocache': { + 'swift.container/a/c': { + 'meta': {'Temp-URL-Key': 'container-key', + 'Temp-URL-Key-2': 'common-key'}}, + 'swift.container/a': { + 'meta': {'Temp-URL-Key': 'account-key', + 'Temp-URL-Key-2': 'common-key'}}}} + + req_other_object = Request.blank("/v1/a/c/o2") + req_other_container = Request.blank("/v1/a/c2/o2") + req_other_account = Request.blank("/v1/a2/c2/o2") + + # A request with the account key limits the pre-authed scope to the + # account level. + method = 'GET' + expires = int(time() + 86400) + path = '/v1/a/c/o' + key = 'account-key' + hmac_body = '%s\n%s\n%s' % (method, expires, path) + sig = hmac.new(key, hmac_body, sha1).hexdigest() + + environ['REQUEST_METHOD'] = 'GET' + environ['QUERY_STRING'] = 'temp_url_sig=%s&temp_url_expires=%s' % ( + sig, expires) + + req = self._make_request(path, keys=[key], environ=environ) + resp = req.get_response(self.tempurl) + self.assertEquals(resp.status_int, 404) # sanity check + + authorize = req.environ['swift.authorize'] + # Requests for other objects happen if, for example, you're + # downloading a large object or creating a large-object manifest. + oo_resp = authorize(req_other_object) + self.assertEqual(oo_resp, None) + oc_resp = authorize(req_other_container) + self.assertEqual(oc_resp, None) + oa_resp = authorize(req_other_account) + self.assertEqual(oa_resp.status_int, 401) + + # A request with the container key limits the pre-authed scope to + # the container level; a different container in the same account is + # out of scope and thus forbidden. + key = 'container-key' + hmac_body = '%s\n%s\n%s' % (method, expires, path) + sig = hmac.new(key, hmac_body, sha1).hexdigest() + + environ['QUERY_STRING'] = 'temp_url_sig=%s&temp_url_expires=%s' % ( + sig, expires) + + req = self._make_request(path, keys=[key], environ=environ) + resp = req.get_response(self.tempurl) + self.assertEquals(resp.status_int, 404) # sanity check + + authorize = req.environ['swift.authorize'] + oo_resp = authorize(req_other_object) + self.assertEqual(oo_resp, None) + oc_resp = authorize(req_other_container) + self.assertEqual(oc_resp, None) + oa_resp = authorize(req_other_account) + self.assertEqual(oa_resp.status_int, 401) + + # If account and container share a key (users set these, so this can + # happen by accident, stupidity, *or* malice!), limit the scope to + # account level. This prevents someone from shrinking the scope of + # account-level tempurls by reusing one of the account's keys on a + # container. + key = 'shared-key' + hmac_body = '%s\n%s\n%s' % (method, expires, path) + sig = hmac.new(key, hmac_body, sha1).hexdigest() + + environ['QUERY_STRING'] = 'temp_url_sig=%s&temp_url_expires=%s' % ( + sig, expires) + + req = self._make_request(path, keys=[key], environ=environ) + resp = req.get_response(self.tempurl) + self.assertEquals(resp.status_int, 404) # sanity check + + authorize = req.environ['swift.authorize'] + oo_resp = authorize(req_other_object) + self.assertEqual(oo_resp, None) + oc_resp = authorize(req_other_container) + self.assertEqual(oc_resp, None) + oa_resp = authorize(req_other_account) + self.assertEqual(oa_resp.status_int, 401) + def test_changed_path_invalid(self): method = 'GET' expires = int(time() + 86400) @@ -809,35 +902,38 @@ class TestTempURL(unittest.TestCase): self.assertTrue('x-conflict-header-test' in resp.headers) self.assertEqual(resp.headers['x-conflict-header-test'], 'value') - def test_get_account(self): - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'HEAD', 'PATH_INFO': '/v1/a/c/o'}), 'a') - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c/o'}), 'a') - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'PUT', 'PATH_INFO': '/v1/a/c/o'}), 'a') - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'POST', 'PATH_INFO': '/v1/a/c/o'}), 'a') - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'DELETE', 'PATH_INFO': '/v1/a/c/o'}), 'a') - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'UNKNOWN', 'PATH_INFO': '/v1/a/c/o'}), None) - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c/'}), None) - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c//////'}), None) - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c///o///'}), 'a') - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c'}), None) - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a//o'}), None) - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1//c/o'}), None) - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '//a/c/o'}), None) - self.assertEquals(self.tempurl._get_account({ - 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v2/a/c/o'}), None) + def test_get_account_and_container(self): + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'HEAD', 'PATH_INFO': '/v1/a/c/o'}), ('a', 'c')) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c/o'}), ('a', 'c')) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'PUT', 'PATH_INFO': '/v1/a/c/o'}), ('a', 'c')) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'POST', 'PATH_INFO': '/v1/a/c/o'}), ('a', 'c')) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'DELETE', 'PATH_INFO': '/v1/a/c/o'}), ('a', 'c')) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'UNKNOWN', 'PATH_INFO': '/v1/a/c/o'}), + (None, None)) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c/'}), (None, None)) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c//////'}), + (None, None)) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c///o///'}), + ('a', 'c')) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c'}), (None, None)) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a//o'}), (None, None)) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1//c/o'}), (None, None)) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '//a/c/o'}), (None, None)) + self.assertEquals(self.tempurl._get_account_and_container({ + 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v2/a/c/o'}), (None, None)) def test_get_temp_url_info(self): s = 'f5d5051bddf5df7e27c628818738334f' @@ -889,13 +985,13 @@ class TestTempURL(unittest.TestCase): self.assertEquals( self.tempurl._get_hmacs( {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/v1/a/c/o'}, - 1, ['abc']), - ['026d7f7cc25256450423c7ad03fc9f5ffc1dab6d']) + 1, [('abc', 'account')]), + [('026d7f7cc25256450423c7ad03fc9f5ffc1dab6d', 'account')]) self.assertEquals( self.tempurl._get_hmacs( {'REQUEST_METHOD': 'HEAD', 'PATH_INFO': '/v1/a/c/o'}, - 1, ['abc'], request_method='GET'), - ['026d7f7cc25256450423c7ad03fc9f5ffc1dab6d']) + 1, [('abc', 'account')], request_method='GET'), + [('026d7f7cc25256450423c7ad03fc9f5ffc1dab6d', 'account')]) def test_invalid(self): diff --git a/test/unit/proxy/controllers/test_account.py b/test/unit/proxy/controllers/test_account.py index 23ad0a1..c558959 100644 --- a/test/unit/proxy/controllers/test_account.py +++ b/test/unit/proxy/controllers/test_account.py @@ -43,9 +43,11 @@ class TestAccountController(unittest.TestCase): req = Request.blank('/v1/AUTH_bob', {'PATH_INFO': '/v1/AUTH_bob'}) resp = controller.HEAD(req) self.assertEqual(2, resp.status_int // 100) - self.assertTrue('swift.account/AUTH_bob' in resp.environ) - self.assertEqual(headers_to_account_info(resp.headers), - resp.environ['swift.account/AUTH_bob']) + self.assertTrue( + 'swift.account/AUTH_bob' in resp.environ['swift.infocache']) + self.assertEqual( + headers_to_account_info(resp.headers), + resp.environ['swift.infocache']['swift.account/AUTH_bob']) def test_swift_owner(self): owner_headers = { diff --git a/test/unit/proxy/controllers/test_base.py b/test/unit/proxy/controllers/test_base.py index 0ebd96e..b751889 100644 --- a/test/unit/proxy/controllers/test_base.py +++ b/test/unit/proxy/controllers/test_base.py @@ -167,31 +167,37 @@ class TestFuncs(unittest.TestCase): 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'object', iter(nodes), 'part', '/a/c/o/with/slashes') - self.assertTrue('swift.object/a/c/o/with/slashes' in resp.environ) + infocache = resp.environ['swift.infocache'] + self.assertTrue('swift.object/a/c/o/with/slashes' in infocache) self.assertEqual( - resp.environ['swift.object/a/c/o/with/slashes']['status'], 200) + infocache['swift.object/a/c/o/with/slashes']['status'], 200) + req = Request.blank('/v1/a/c/o') with patch('swift.proxy.controllers.base.' 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'object', iter(nodes), 'part', '/a/c/o') - self.assertTrue('swift.object/a/c/o' in resp.environ) - self.assertEqual(resp.environ['swift.object/a/c/o']['status'], 200) + infocache = resp.environ['swift.infocache'] + self.assertTrue('swift.object/a/c/o' in infocache) + self.assertEqual(infocache['swift.object/a/c/o']['status'], 200) + req = Request.blank('/v1/a/c') with patch('swift.proxy.controllers.base.' 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'container', iter(nodes), 'part', '/a/c') - self.assertTrue('swift.container/a/c' in resp.environ) - self.assertEqual(resp.environ['swift.container/a/c']['status'], 200) + infocache = resp.environ['swift.infocache'] + self.assertTrue('swift.container/a/c' in infocache) + self.assertEqual(infocache['swift.container/a/c']['status'], 200) req = Request.blank('/v1/a') with patch('swift.proxy.controllers.base.' 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'account', iter(nodes), 'part', '/a') - self.assertTrue('swift.account/a' in resp.environ) - self.assertEqual(resp.environ['swift.account/a']['status'], 200) + infocache = resp.environ['swift.infocache'] + self.assertTrue('swift.account/a' in infocache) + self.assertEqual(infocache['swift.account/a']['status'], 200) def test_get_info(self): app = FakeApp() @@ -203,7 +209,8 @@ class TestFuncs(unittest.TestCase): self.assertEquals(info_a['bytes'], 6666) self.assertEquals(info_a['total_object_count'], 1000) # Make sure the env cache is set - self.assertEquals(env.get('swift.account/a'), info_a) + self.assertEquals(env['swift.infocache'].get('swift.account/a'), + info_a) # Make sure the app was called self.assertEqual(app.responses.stats['account'], 1) @@ -214,7 +221,8 @@ class TestFuncs(unittest.TestCase): self.assertEquals(info_a['bytes'], 6666) self.assertEquals(info_a['total_object_count'], 1000) # Make sure the env cache is set - self.assertEquals(env.get('swift.account/a'), info_a) + self.assertEquals(env['swift.infocache'].get('swift.account/a'), + info_a) # Make sure the app was NOT called AGAIN self.assertEqual(app.responses.stats['account'], 1) @@ -225,8 +233,10 @@ class TestFuncs(unittest.TestCase): self.assertEquals(info_c['bytes'], 6666) self.assertEquals(info_c['object_count'], 1000) # Make sure the env cache is set - self.assertEquals(env.get('swift.account/a'), info_a) - self.assertEquals(env.get('swift.container/a/c'), info_c) + self.assertEquals(env['swift.infocache'].get('swift.account/a'), + info_a) + self.assertEquals(env['swift.infocache'].get('swift.container/a/c'), + info_c) # Make sure the app was called for container self.assertEqual(app.responses.stats['container'], 1) @@ -240,22 +250,25 @@ class TestFuncs(unittest.TestCase): self.assertEquals(info_c['bytes'], 6666) self.assertEquals(info_c['object_count'], 1000) # Make sure the env cache is set - self.assertEquals(env.get('swift.account/a'), info_a) - self.assertEquals(env.get('swift.container/a/c'), info_c) + self.assertEquals(env['swift.infocache'].get('swift.account/a'), + info_a) + self.assertEquals(env['swift.infocache'].get('swift.container/a/c'), + info_c) # check app calls both account and container self.assertEqual(app.responses.stats['account'], 1) self.assertEqual(app.responses.stats['container'], 1) # This time do an env cached call to container while account is not # cached - del(env['swift.account/a']) + del(env['swift.infocache']['swift.account/a']) info_c = get_info(app, env, 'a', 'c') # Check that you got proper info self.assertEquals(info_a['status'], 200) self.assertEquals(info_c['bytes'], 6666) self.assertEquals(info_c['object_count'], 1000) # Make sure the env cache is set and account still not cached - self.assertEquals(env.get('swift.container/a/c'), info_c) + self.assertEquals(env['swift.infocache'].get('swift.container/a/c'), + info_c) # no additional calls were made self.assertEqual(app.responses.stats['account'], 1) self.assertEqual(app.responses.stats['container'], 1) @@ -269,7 +282,8 @@ class TestFuncs(unittest.TestCase): self.assertEquals(info_a['bytes'], None) self.assertEquals(info_a['total_object_count'], None) # Make sure the env cache is set - self.assertEquals(env.get('swift.account/a'), info_a) + self.assertEquals(env['swift.infocache'].get('swift.account/a'), + info_a) # and account was called self.assertEqual(app.responses.stats['account'], 1) @@ -280,7 +294,8 @@ class TestFuncs(unittest.TestCase): self.assertEquals(info_a['bytes'], None) self.assertEquals(info_a['total_object_count'], None) # Make sure the env cache is set - self.assertEquals(env.get('swift.account/a'), info_a) + self.assertEquals(env['swift.infocache'].get('swift.account/a'), + info_a) # add account was NOT called AGAIN self.assertEqual(app.responses.stats['account'], 1) @@ -290,7 +305,8 @@ class TestFuncs(unittest.TestCase): info_a = get_info(app, env, 'a') # Check that you got proper info self.assertEquals(info_a, None) - self.assertEquals(env['swift.account/a']['status'], 404) + self.assertEquals(env['swift.infocache']['swift.account/a']['status'], + 404) # and account was called self.assertEqual(app.responses.stats['account'], 1) @@ -298,7 +314,8 @@ class TestFuncs(unittest.TestCase): info_a = get_info(None, env, 'a') # Check that you got proper info self.assertEquals(info_a, None) - self.assertEquals(env['swift.account/a']['status'], 404) + self.assertEquals(env['swift.infocache']['swift.account/a']['status'], + 404) # add account was NOT called AGAIN self.assertEqual(app.responses.stats['account'], 1) @@ -356,9 +373,10 @@ class TestFuncs(unittest.TestCase): def test_get_container_info_env(self): cache_key = get_container_memcache_key("account", "cont") env_key = 'swift.%s' % cache_key - req = Request.blank("/v1/account/cont", - environ={env_key: {'bytes': 3867}, - 'swift.cache': FakeCache({})}) + req = Request.blank( + "/v1/account/cont", + environ={'swift.infocache': {env_key: {'bytes': 3867}}, + 'swift.cache': FakeCache({})}) resp = get_container_info(req.environ, 'xxx') self.assertEquals(resp['bytes'], 3867) @@ -406,9 +424,10 @@ class TestFuncs(unittest.TestCase): def test_get_account_info_env(self): cache_key = get_account_memcache_key("account") env_key = 'swift.%s' % cache_key - req = Request.blank("/v1/account", - environ={env_key: {'bytes': 3867}, - 'swift.cache': FakeCache({})}) + req = Request.blank( + "/v1/account", + environ={'swift.infocache': {env_key: {'bytes': 3867}}, + 'swift.cache': FakeCache({})}) resp = get_account_info(req.environ, 'xxx') self.assertEquals(resp['bytes'], 3867) @@ -418,9 +437,10 @@ class TestFuncs(unittest.TestCase): 'type': 'application/json', 'meta': {}} env_key = get_object_env_key("account", "cont", "obj") - req = Request.blank("/v1/account/cont/obj", - environ={env_key: cached, - 'swift.cache': FakeCache({})}) + req = Request.blank( + "/v1/account/cont/obj", + environ={'swift.infocache': {env_key: cached}, + 'swift.cache': FakeCache({})}) resp = get_object_info(req.environ, 'xxx') self.assertEquals(resp['length'], 3333) self.assertEquals(resp['type'], 'application/json') diff --git a/test/unit/proxy/controllers/test_container.py b/test/unit/proxy/controllers/test_container.py index 59bbd05..cb9ff2a 100644 --- a/test/unit/proxy/controllers/test_container.py +++ b/test/unit/proxy/controllers/test_container.py @@ -75,9 +75,11 @@ class TestContainerController(TestRingBase): req = Request.blank('/v1/a/c', {'PATH_INFO': '/v1/a/c'}) resp = controller.HEAD(req) self.assertEqual(2, resp.status_int // 100) - self.assertTrue("swift.container/a/c" in resp.environ) - self.assertEqual(headers_to_container_info(resp.headers), - resp.environ['swift.container/a/c']) + self.assertTrue( + "swift.container/a/c" in resp.environ['swift.infocache']) + self.assertEqual( + headers_to_container_info(resp.headers), + resp.environ['swift.infocache']['swift.container/a/c']) def test_swift_owner(self): owner_headers = { @@ -89,6 +91,7 @@ class TestContainerController(TestRingBase): with mock.patch('swift.proxy.controllers.base.http_connect', fake_http_connect(200, 200, headers=owner_headers)): resp = controller.HEAD(req) + self.assertEquals(2, resp.status_int // 100) for key in owner_headers: self.assertTrue(key not in resp.headers) diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py index 3319696..4ba6189 100644 --- a/test/unit/proxy/test_server.py +++ b/test/unit/proxy/test_server.py @@ -6682,19 +6682,20 @@ class TestContainerController(unittest.TestCase): if expected < 400: self.assert_('x-works' in res.headers) self.assertEquals(res.headers['x-works'], 'yes') + ic = res.environ.get('swift.infocache', {}) if c_expected: - self.assertTrue('swift.container/a/c' in res.environ) + self.assertTrue('swift.container/a/c' in ic) self.assertEquals( - res.environ['swift.container/a/c']['status'], + ic['swift.container/a/c']['status'], c_expected) else: - self.assertTrue('swift.container/a/c' not in res.environ) + self.assertTrue('swift.container/a/c' not in ic) if a_expected: - self.assertTrue('swift.account/a' in res.environ) - self.assertEquals(res.environ['swift.account/a']['status'], + self.assertTrue('swift.account/a' in ic) + self.assertEquals(ic['swift.account/a']['status'], a_expected) else: - self.assertTrue('swift.account/a' not in res.environ) + self.assertTrue('swift.account/a' not in ic) set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} @@ -6706,19 +6707,20 @@ class TestContainerController(unittest.TestCase): if expected < 400: self.assert_('x-works' in res.headers) self.assertEquals(res.headers['x-works'], 'yes') + ic = res.environ.get('swift.infocache', {}) if c_expected: - self.assertTrue('swift.container/a/c' in res.environ) + self.assertTrue('swift.container/a/c' in ic) self.assertEquals( - res.environ['swift.container/a/c']['status'], + ic['swift.container/a/c']['status'], c_expected) else: - self.assertTrue('swift.container/a/c' not in res.environ) + self.assertTrue('swift.container/a/c' not in ic) if a_expected: - self.assertTrue('swift.account/a' in res.environ) - self.assertEquals(res.environ['swift.account/a']['status'], + self.assertTrue('swift.account/a' in ic) + self.assertEquals(ic['swift.account/a']['status'], a_expected) else: - self.assertTrue('swift.account/a' not in res.environ) + self.assertTrue('swift.account/a' not in ic) # In all the following tests cache 200 for account # return and ache vary for container # return 200 and cache 200 for and container @@ -7331,7 +7333,8 @@ class TestContainerController(unittest.TestCase): res = controller.GET(req) self.assertEquals(res.status_int, 204) self.assertEquals( - res.environ['swift.container/a/c']['status'], 204) + res.environ['swift.infocache'][ + 'swift.container/a/c']['status'], 204) self.assertEquals(res.content_length, 0) self.assertTrue('transfer-encoding' not in res.headers) @@ -7349,7 +7352,9 @@ class TestContainerController(unittest.TestCase): req.environ['swift.authorize'] = authorize self.app.update_request(req) res = controller.GET(req) - self.assertEquals(res.environ['swift.container/a/c']['status'], 201) + self.assertEquals( + res.environ['swift.infocache']['swift.container/a/c']['status'], + 201) self.assert_(called[0]) def test_HEAD_calls_authorize(self): @@ -7818,7 +7823,8 @@ class TestAccountController(unittest.TestCase): res = method(req) self.assertEquals(res.status_int, expected) if env_expected: - self.assertEquals(res.environ['swift.account/a']['status'], + ic = res.environ['swift.infocache'] + self.assertEquals(ic['swift.account/a']['status'], env_expected) set_http_connect(*statuses) req = Request.blank('/v1/a/', {}) @@ -7826,7 +7832,8 @@ class TestAccountController(unittest.TestCase): res = method(req) self.assertEquals(res.status_int, expected) if env_expected: - self.assertEquals(res.environ['swift.account/a']['status'], + ic = res.environ['swift.infocache'] + self.assertEquals(ic['swift.account/a']['status'], env_expected) def test_OPTIONS(self):