Stop staticweb revealing container existence to unauth'd requests
When a container has `X-Container-Meta-Web-Listings: false` then staticweb will return a 404 in response to a GET or HEAD on the container, regardless of whether the request is auth'd. That provides a way to probe for container existence. It should return a 401 if the request is not auth'd. This patch adds a call to swift.authorize before returning the 404. Closes-Bug: 1506116 Change-Id: I382323b49dc8f6d67bf4494db7084a860a10db59
This commit is contained in:
committed by
Alistair Coles
parent
9e53bb47ef
commit
75ab3cb788
@@ -131,7 +131,8 @@ from swift.common.utils import human_readable, split_path, config_true_value, \
|
||||
quote, register_swift_info, get_logger
|
||||
from swift.common.wsgi import make_env, WSGIContext
|
||||
from swift.common.http import is_success, is_redirection, HTTP_NOT_FOUND
|
||||
from swift.common.swob import Response, HTTPMovedPermanently, HTTPNotFound
|
||||
from swift.common.swob import Response, HTTPMovedPermanently, HTTPNotFound, \
|
||||
Request
|
||||
from swift.proxy.controllers.base import get_container_info
|
||||
|
||||
|
||||
@@ -196,10 +197,12 @@ class _StaticWebContext(WSGIContext):
|
||||
self._error, self._listings, self._listings_css and self._dir_type.
|
||||
|
||||
:param env: The WSGI environment dict.
|
||||
:return container_info: The container_info dict.
|
||||
"""
|
||||
self._index = self._error = self._listings = self._listings_css = \
|
||||
self._dir_type = None
|
||||
container_info = get_container_info(env, self.app, swift_source='SW')
|
||||
container_info = get_container_info(
|
||||
env, self.app, swift_source='SW')
|
||||
if is_success(container_info['status']):
|
||||
meta = container_info.get('meta', {})
|
||||
self._index = meta.get('web-index', '').strip()
|
||||
@@ -208,6 +211,7 @@ class _StaticWebContext(WSGIContext):
|
||||
self._listings_label = meta.get('web-listings-label', '').strip()
|
||||
self._listings_css = meta.get('web-listings-css', '').strip()
|
||||
self._dir_type = meta.get('web-directory-type', '').strip()
|
||||
return container_info
|
||||
|
||||
def _listing(self, env, start_response, prefix=None):
|
||||
"""
|
||||
@@ -356,7 +360,15 @@ class _StaticWebContext(WSGIContext):
|
||||
:param env: The original WSGI environment dict.
|
||||
:param start_response: The original WSGI start_response hook.
|
||||
"""
|
||||
self._get_container_info(env)
|
||||
container_info = self._get_container_info(env)
|
||||
req = Request(env)
|
||||
req.acl = container_info['read_acl']
|
||||
# we checked earlier that swift.authorize is set in env
|
||||
aresp = env['swift.authorize'](req)
|
||||
if aresp:
|
||||
resp = aresp(env, self._start_response)
|
||||
return self._error_response(resp, env, start_response)
|
||||
|
||||
if not self._listings and not self._index:
|
||||
if config_true_value(env.get('HTTP_X_WEB_MODE', 'f')):
|
||||
return HTTPNotFound()(env, start_response)
|
||||
|
||||
@@ -41,7 +41,8 @@ meta_map = {
|
||||
'web-error': 'error.html'}},
|
||||
'c6b': {'meta': {'web-listings': 't',
|
||||
'web-listings-label': 'foo'}},
|
||||
'c7': {'meta': {'web-listings': 'f'}},
|
||||
'c7': {'meta': {'web-listings': 'f',
|
||||
'web-error': 'error.html'}},
|
||||
'c8': {'meta': {'web-error': 'error.html',
|
||||
'web-listings': 't',
|
||||
'web-listings-css':
|
||||
@@ -202,6 +203,16 @@ class FakeApp(object):
|
||||
'''.strip())(env, start_response)
|
||||
elif env['PATH_INFO'] in ('/v1/a/c7', '/v1/a/c7/'):
|
||||
return self.listing(env, start_response)
|
||||
elif env['PATH_INFO'] == '/v1/a/c7/404error.html':
|
||||
return Response(status='404 Not Found')(env, start_response)
|
||||
elif env['PATH_INFO'] == '/v1/a/c7/401error.html':
|
||||
return Response(status='200 Ok', body='''
|
||||
<html>
|
||||
<body style="background: #000000; color: #ffaaaa">
|
||||
<p>Hey, you're not authorized to see this!</p>
|
||||
</body>
|
||||
</html>
|
||||
'''.strip())(env, start_response)
|
||||
elif env['PATH_INFO'] in ('/v1/a/c8', '/v1/a/c8/'):
|
||||
return self.listing(env, start_response)
|
||||
elif env['PATH_INFO'] == '/v1/a/c8/subdir/':
|
||||
@@ -663,9 +674,37 @@ class TestStaticWeb(unittest.TestCase):
|
||||
self.assertIn(label, resp.body)
|
||||
|
||||
def test_container7listing(self):
|
||||
# container7 has web-listings = f, web-error=error.html
|
||||
resp = Request.blank('/v1/a/c7/').get_response(self.test_staticweb)
|
||||
self.assertEqual(resp.status_int, 404)
|
||||
self.assertTrue('Web Listing Disabled' in resp.body)
|
||||
self.assertIn("Web Listing Disabled", resp.body)
|
||||
|
||||
# expect 301 if auth'd but no trailing '/'
|
||||
resp = Request.blank('/v1/a/c7').get_response(self.test_staticweb)
|
||||
self.assertEqual(resp.status_int, 301)
|
||||
|
||||
# expect default 401 if request is not auth'd and no trailing '/'
|
||||
test_staticweb = FakeAuthFilter(
|
||||
staticweb.filter_factory({})(self.app), deny_listing=True,
|
||||
deny_objects=True)
|
||||
resp = Request.blank('/v1/a/c7').get_response(test_staticweb)
|
||||
self.assertEqual(resp.status_int, 401)
|
||||
self.assertNotIn("Hey, you're not authorized to see this!", resp.body)
|
||||
|
||||
# expect custom 401 if request is not auth'd for listing
|
||||
test_staticweb = FakeAuthFilter(
|
||||
staticweb.filter_factory({})(self.app), deny_listing=True)
|
||||
resp = Request.blank('/v1/a/c7/').get_response(test_staticweb)
|
||||
self.assertEqual(resp.status_int, 401)
|
||||
self.assertIn("Hey, you're not authorized to see this!", resp.body)
|
||||
|
||||
# expect default 401 if request is not auth'd for listing or object GET
|
||||
test_staticweb = FakeAuthFilter(
|
||||
staticweb.filter_factory({})(self.app), deny_listing=True,
|
||||
deny_objects=True)
|
||||
resp = Request.blank('/v1/a/c7/').get_response(test_staticweb)
|
||||
self.assertEqual(resp.status_int, 401)
|
||||
self.assertNotIn("Hey, you're not authorized to see this!", resp.body)
|
||||
|
||||
def test_container8listingcss(self):
|
||||
resp = Request.blank(
|
||||
|
||||
Reference in New Issue
Block a user