Add WWW-Authenticate to 401 responses
Per http://www.ietf.org/rfc/rfc2616.txt, when a 401 error is returned, the Www-Authenticate response header MUST also be returned. The format is described in http://www.ietf.org/rfc/rfc2617.txt. Swift supports and/or implements a number of authentication schemes including tempauth, Keystone, tempurl, formpost and container sync. In this fix, we use a catch-all, "Swift". The realm is the account (where known) or "unknown" (bad path or where the 401 is returned from code that does not have the request). Examples: Www-Authenticate: Swift realm="AUTH_1234567889" Www-Authenticate: Swift realm="unknown" Fixes bug #1215491 Change-Id: I03362789318dfa156d3733ef9348795062a9cfc4
This commit is contained in:
parent
0c6764ba30
commit
9807a358c6
@ -111,6 +111,7 @@ from urllib import quote
|
|||||||
from swift.common.middleware.tempurl import get_tempurl_keys_from_metadata
|
from swift.common.middleware.tempurl import get_tempurl_keys_from_metadata
|
||||||
from swift.common.utils import streq_const_time
|
from swift.common.utils import streq_const_time
|
||||||
from swift.common.wsgi import make_pre_authed_env
|
from swift.common.wsgi import make_pre_authed_env
|
||||||
|
from swift.common.swob import HTTPUnauthorized
|
||||||
from swift.proxy.controllers.base import get_account_info
|
from swift.proxy.controllers.base import get_account_info
|
||||||
|
|
||||||
|
|
||||||
@ -129,6 +130,10 @@ class FormInvalid(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FormUnauthorized(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _parse_attrs(header):
|
def _parse_attrs(header):
|
||||||
"""
|
"""
|
||||||
Given the value of a header like:
|
Given the value of a header like:
|
||||||
@ -327,6 +332,10 @@ class FormPost(object):
|
|||||||
(('Content-Type', 'text/plain'),
|
(('Content-Type', 'text/plain'),
|
||||||
('Content-Length', str(len(body)))))
|
('Content-Length', str(len(body)))))
|
||||||
return [body]
|
return [body]
|
||||||
|
except FormUnauthorized as err:
|
||||||
|
message = 'FormPost: %s' % str(err).title()
|
||||||
|
return HTTPUnauthorized(body=message)(
|
||||||
|
env, start_response)
|
||||||
return self.app(env, start_response)
|
return self.app(env, start_response)
|
||||||
|
|
||||||
def _translate_form(self, env, boundary):
|
def _translate_form(self, env, boundary):
|
||||||
@ -410,7 +419,7 @@ class FormPost(object):
|
|||||||
:returns: (status_line, message)
|
:returns: (status_line, message)
|
||||||
"""
|
"""
|
||||||
if not keys:
|
if not keys:
|
||||||
return '401 Unauthorized', 'invalid signature'
|
raise FormUnauthorized('invalid signature')
|
||||||
try:
|
try:
|
||||||
max_file_size = int(attributes.get('max_file_size') or 0)
|
max_file_size = int(attributes.get('max_file_size') or 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -432,7 +441,7 @@ class FormPost(object):
|
|||||||
del subenv['CONTENT_TYPE']
|
del subenv['CONTENT_TYPE']
|
||||||
try:
|
try:
|
||||||
if int(attributes.get('expires') or 0) < time():
|
if int(attributes.get('expires') or 0) < time():
|
||||||
return '401 Unauthorized', 'form expired'
|
raise FormUnauthorized('form expired')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise FormInvalid('expired not an integer')
|
raise FormInvalid('expired not an integer')
|
||||||
hmac_body = '%s\n%s\n%s\n%s\n%s' % (
|
hmac_body = '%s\n%s\n%s\n%s\n%s' % (
|
||||||
@ -449,7 +458,7 @@ class FormPost(object):
|
|||||||
'invalid')):
|
'invalid')):
|
||||||
has_valid_sig = True
|
has_valid_sig = True
|
||||||
if not has_valid_sig:
|
if not has_valid_sig:
|
||||||
return '401 Unauthorized', 'invalid signature'
|
raise FormUnauthorized('invalid signature')
|
||||||
|
|
||||||
substatus = [None]
|
substatus = [None]
|
||||||
|
|
||||||
|
@ -156,7 +156,14 @@ class TempAuth(object):
|
|||||||
# Because I know I'm the definitive auth for this token, I
|
# Because I know I'm the definitive auth for this token, I
|
||||||
# can deny it outright.
|
# can deny it outright.
|
||||||
self.logger.increment('unauthorized')
|
self.logger.increment('unauthorized')
|
||||||
return HTTPUnauthorized()(env, start_response)
|
try:
|
||||||
|
vrs, realm, rest = split_path(env['PATH_INFO'],
|
||||||
|
2, 3, True)
|
||||||
|
except ValueError:
|
||||||
|
realm = 'unknown'
|
||||||
|
return HTTPUnauthorized(headers={
|
||||||
|
'Www-Authenticate': 'Swift realm="%s"' % realm})(
|
||||||
|
env, start_response)
|
||||||
# Because I'm not certain if I'm the definitive auth for empty
|
# Because I'm not certain if I'm the definitive auth for empty
|
||||||
# reseller_prefixed tokens, I won't overwrite swift.authorize.
|
# reseller_prefixed tokens, I won't overwrite swift.authorize.
|
||||||
elif 'swift.authorize' not in env:
|
elif 'swift.authorize' not in env:
|
||||||
@ -408,11 +415,15 @@ class TempAuth(object):
|
|||||||
user = req.headers.get('x-auth-user')
|
user = req.headers.get('x-auth-user')
|
||||||
if not user or ':' not in user:
|
if not user or ':' not in user:
|
||||||
self.logger.increment('token_denied')
|
self.logger.increment('token_denied')
|
||||||
return HTTPUnauthorized(request=req)
|
return HTTPUnauthorized(request=req, headers=
|
||||||
|
{'Www-Authenticate':
|
||||||
|
'Swift realm="%s"' % account})
|
||||||
account2, user = user.split(':', 1)
|
account2, user = user.split(':', 1)
|
||||||
if account != account2:
|
if account != account2:
|
||||||
self.logger.increment('token_denied')
|
self.logger.increment('token_denied')
|
||||||
return HTTPUnauthorized(request=req)
|
return HTTPUnauthorized(request=req, headers=
|
||||||
|
{'Www-Authenticate':
|
||||||
|
'Swift realm="%s"' % account})
|
||||||
key = req.headers.get('x-storage-pass')
|
key = req.headers.get('x-storage-pass')
|
||||||
if not key:
|
if not key:
|
||||||
key = req.headers.get('x-auth-key')
|
key = req.headers.get('x-auth-key')
|
||||||
@ -422,7 +433,9 @@ class TempAuth(object):
|
|||||||
user = req.headers.get('x-storage-user')
|
user = req.headers.get('x-storage-user')
|
||||||
if not user or ':' not in user:
|
if not user or ':' not in user:
|
||||||
self.logger.increment('token_denied')
|
self.logger.increment('token_denied')
|
||||||
return HTTPUnauthorized(request=req)
|
return HTTPUnauthorized(request=req, headers=
|
||||||
|
{'Www-Authenticate':
|
||||||
|
'Swift realm="unknown"'})
|
||||||
account, user = user.split(':', 1)
|
account, user = user.split(':', 1)
|
||||||
key = req.headers.get('x-auth-key')
|
key = req.headers.get('x-auth-key')
|
||||||
if not key:
|
if not key:
|
||||||
@ -431,15 +444,22 @@ class TempAuth(object):
|
|||||||
return HTTPBadRequest(request=req)
|
return HTTPBadRequest(request=req)
|
||||||
if not all((account, user, key)):
|
if not all((account, user, key)):
|
||||||
self.logger.increment('token_denied')
|
self.logger.increment('token_denied')
|
||||||
return HTTPUnauthorized(request=req)
|
realm = account or 'unknown'
|
||||||
|
return HTTPUnauthorized(request=req, headers={'Www-Authenticate':
|
||||||
|
'Swift realm="%s"' %
|
||||||
|
realm})
|
||||||
# Authenticate user
|
# Authenticate user
|
||||||
account_user = account + ':' + user
|
account_user = account + ':' + user
|
||||||
if account_user not in self.users:
|
if account_user not in self.users:
|
||||||
self.logger.increment('token_denied')
|
self.logger.increment('token_denied')
|
||||||
return HTTPUnauthorized(request=req)
|
return HTTPUnauthorized(request=req, headers=
|
||||||
|
{'Www-Authenticate':
|
||||||
|
'Swift realm="%s"' % account})
|
||||||
if self.users[account_user]['key'] != key:
|
if self.users[account_user]['key'] != key:
|
||||||
self.logger.increment('token_denied')
|
self.logger.increment('token_denied')
|
||||||
return HTTPUnauthorized(request=req)
|
return HTTPUnauthorized(request=req, headers=
|
||||||
|
{'Www-Authenticate':
|
||||||
|
'Swift realm="unknown"'})
|
||||||
account_id = self.users[account_user]['url'].rsplit('/', 1)[-1]
|
account_id = self.users[account_user]['url'].rsplit('/', 1)[-1]
|
||||||
# Get memcache client
|
# Get memcache client
|
||||||
memcache_client = cache_from_env(req.environ)
|
memcache_client = cache_from_env(req.environ)
|
||||||
|
@ -99,6 +99,7 @@ from urlparse import parse_qs
|
|||||||
from swift.proxy.controllers.base import get_account_info
|
from swift.proxy.controllers.base import get_account_info
|
||||||
from swift.common.swob import HeaderKeyDict
|
from swift.common.swob import HeaderKeyDict
|
||||||
from swift.common.utils import split_path
|
from swift.common.utils import split_path
|
||||||
|
from swift.common.swob import HTTPUnauthorized
|
||||||
|
|
||||||
|
|
||||||
#: Default headers to remove from incoming requests. Simply a whitespace
|
#: Default headers to remove from incoming requests. Simply a whitespace
|
||||||
@ -412,13 +413,11 @@ class TempURL(object):
|
|||||||
:param start_response: The WSGI start_response hook.
|
:param start_response: The WSGI start_response hook.
|
||||||
:returns: 401 response as per WSGI.
|
:returns: 401 response as per WSGI.
|
||||||
"""
|
"""
|
||||||
body = '401 Unauthorized: Temp URL invalid\n'
|
|
||||||
start_response('401 Unauthorized',
|
|
||||||
[('Content-Type', 'text/plain'),
|
|
||||||
('Content-Length', str(len(body)))])
|
|
||||||
if env['REQUEST_METHOD'] == 'HEAD':
|
if env['REQUEST_METHOD'] == 'HEAD':
|
||||||
return []
|
body = None
|
||||||
return [body]
|
else:
|
||||||
|
body = '401 Unauthorized: Temp URL invalid\n'
|
||||||
|
return HTTPUnauthorized(body=body)(env, start_response)
|
||||||
|
|
||||||
def _clean_incoming_headers(self, env):
|
def _clean_incoming_headers(self, env):
|
||||||
"""
|
"""
|
||||||
|
@ -1042,6 +1042,8 @@ class Response(object):
|
|||||||
self.environ = {}
|
self.environ = {}
|
||||||
if headers:
|
if headers:
|
||||||
self.headers.update(headers)
|
self.headers.update(headers)
|
||||||
|
if self.status_int == 401 and 'www-authenticate' not in self.headers:
|
||||||
|
self.headers.update({'www-authenticate': self.www_authenticate()})
|
||||||
for key, value in kw.iteritems():
|
for key, value in kw.iteritems():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
# When specifying both 'content_type' and 'charset' in the kwargs,
|
# When specifying both 'content_type' and 'charset' in the kwargs,
|
||||||
@ -1152,6 +1154,21 @@ class Response(object):
|
|||||||
return self.location
|
return self.location
|
||||||
return self.host_url + self.location
|
return self.host_url + self.location
|
||||||
|
|
||||||
|
def www_authenticate(self):
|
||||||
|
"""
|
||||||
|
Construct a suitable value for WWW-Authenticate response header
|
||||||
|
|
||||||
|
If we have a request and a valid-looking path, the realm
|
||||||
|
is the account; otherwise we set it to 'unknown'.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
vrs, realm, rest = self.request.split_path(2, 3, True)
|
||||||
|
if realm in ('v1.0', 'auth'):
|
||||||
|
realm = 'unknown'
|
||||||
|
except (AttributeError, ValueError):
|
||||||
|
realm = 'unknown'
|
||||||
|
return 'Swift realm="%s"' % realm
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_success(self):
|
def is_success(self):
|
||||||
return self.status_int // 100 == 2
|
return self.status_int // 100 == 2
|
||||||
|
@ -392,6 +392,39 @@ class TestFormPost(unittest.TestCase):
|
|||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('FormPost' not in resp.body)
|
self.assertTrue('FormPost' not in resp.body)
|
||||||
|
|
||||||
|
def test_auth_scheme(self):
|
||||||
|
# FormPost rejects
|
||||||
|
key = 'abc'
|
||||||
|
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])
|
||||||
|
self.app = FakeApp(iter([('201 Created', {}, ''),
|
||||||
|
('201 Created', {}, '')]))
|
||||||
|
self.auth = tempauth.filter_factory({})(self.app)
|
||||||
|
self.formpost = formpost.filter_factory({})(self.auth)
|
||||||
|
status = [None]
|
||||||
|
headers = [None]
|
||||||
|
exc_info = [None]
|
||||||
|
|
||||||
|
def start_response(s, h, e=None):
|
||||||
|
status[0] = s
|
||||||
|
headers[0] = h
|
||||||
|
exc_info[0] = e
|
||||||
|
|
||||||
|
body = ''.join(self.formpost(env, start_response))
|
||||||
|
status = status[0]
|
||||||
|
headers = headers[0]
|
||||||
|
exc_info = exc_info[0]
|
||||||
|
self.assertEquals(status, '401 Unauthorized')
|
||||||
|
authenticate_v = None
|
||||||
|
for h, v in headers:
|
||||||
|
if h.lower() == 'www-authenticate':
|
||||||
|
authenticate_v = v
|
||||||
|
self.assertTrue('FormPost: Form Expired' in body)
|
||||||
|
self.assertEquals('Swift realm="unknown"', authenticate_v)
|
||||||
|
|
||||||
def test_safari(self):
|
def test_safari(self):
|
||||||
key = 'abc'
|
key = 'abc'
|
||||||
path = '/v1/AUTH_test/container'
|
path = '/v1/AUTH_test/container'
|
||||||
|
@ -163,6 +163,13 @@ class SwiftAuth(unittest.TestCase):
|
|||||||
resp = req.get_response(self._get_successful_middleware())
|
resp = req.get_response(self._get_successful_middleware())
|
||||||
self.assertEqual(resp.status_int, 200)
|
self.assertEqual(resp.status_int, 200)
|
||||||
|
|
||||||
|
def test_auth_scheme(self):
|
||||||
|
req = self._make_request(path='/v1/BLAH_foo/c/o',
|
||||||
|
headers={'X_IDENTITY_STATUS': 'Invalid'})
|
||||||
|
resp = req.get_response(self.test_auth)
|
||||||
|
self.assertEqual(resp.status_int, 401)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
|
|
||||||
class TestAuthorize(unittest.TestCase):
|
class TestAuthorize(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -143,6 +143,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertEquals(req.environ['swift.authorize'],
|
self.assertEquals(req.environ['swift.authorize'],
|
||||||
self.test_auth.denied_response)
|
self.test_auth.denied_response)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="unknown"')
|
||||||
|
|
||||||
def test_anon(self):
|
def test_anon(self):
|
||||||
req = self._make_request('/v1/AUTH_account')
|
req = self._make_request('/v1/AUTH_account')
|
||||||
@ -150,6 +152,15 @@ class TestAuth(unittest.TestCase):
|
|||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertEquals(req.environ['swift.authorize'],
|
self.assertEquals(req.environ['swift.authorize'],
|
||||||
self.test_auth.authorize)
|
self.test_auth.authorize)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_account"')
|
||||||
|
|
||||||
|
def test_anon_badpath(self):
|
||||||
|
req = self._make_request('/v1')
|
||||||
|
resp = req.get_response(self.test_auth)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="unknown"')
|
||||||
|
|
||||||
def test_override_asked_for_but_not_allowed(self):
|
def test_override_asked_for_but_not_allowed(self):
|
||||||
self.test_auth = \
|
self.test_auth = \
|
||||||
@ -158,6 +169,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
environ={'swift.authorize_override': True})
|
environ={'swift.authorize_override': True})
|
||||||
resp = req.get_response(self.test_auth)
|
resp = req.get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_account"')
|
||||||
self.assertEquals(req.environ['swift.authorize'],
|
self.assertEquals(req.environ['swift.authorize'],
|
||||||
self.test_auth.authorize)
|
self.test_auth.authorize)
|
||||||
|
|
||||||
@ -182,6 +195,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
headers={'X-Auth-Token': 'BLAH_t'})
|
headers={'X-Auth-Token': 'BLAH_t'})
|
||||||
resp = req.get_response(self.test_auth)
|
resp = req.get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="BLAH_account"')
|
||||||
self.assertEquals(req.environ['swift.authorize'],
|
self.assertEquals(req.environ['swift.authorize'],
|
||||||
self.test_auth.denied_response)
|
self.test_auth.denied_response)
|
||||||
|
|
||||||
@ -205,6 +220,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
headers={'X-Auth-Token': 't'})
|
headers={'X-Auth-Token': 't'})
|
||||||
resp = req.get_response(local_auth)
|
resp = req.get_response(local_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="account"')
|
||||||
self.assertEquals(local_app.calls, 1)
|
self.assertEquals(local_app.calls, 1)
|
||||||
self.assertEquals(req.environ['swift.authorize'],
|
self.assertEquals(req.environ['swift.authorize'],
|
||||||
local_auth.denied_response)
|
local_auth.denied_response)
|
||||||
@ -216,6 +233,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
req = self._make_request('/v1/account')
|
req = self._make_request('/v1/account')
|
||||||
resp = req.get_response(local_auth)
|
resp = req.get_response(local_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="account"')
|
||||||
self.assertEquals(req.environ['swift.authorize'],
|
self.assertEquals(req.environ['swift.authorize'],
|
||||||
local_auth.authorize)
|
local_auth.authorize)
|
||||||
# Now make sure we don't override an existing swift.authorize when we
|
# Now make sure we don't override an existing swift.authorize when we
|
||||||
@ -234,11 +253,15 @@ class TestAuth(unittest.TestCase):
|
|||||||
'/v1/AUTH_cfa',
|
'/v1/AUTH_cfa',
|
||||||
headers={'X-Auth-Token': 'AUTH_t'}).get_response(self.test_auth)
|
headers={'X-Auth-Token': 'AUTH_t'}).get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
|
|
||||||
def test_authorize_bad_path(self):
|
def test_authorize_bad_path(self):
|
||||||
req = self._make_request('/badpath')
|
req = self._make_request('/badpath')
|
||||||
resp = self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="unknown"')
|
||||||
req = self._make_request('/badpath')
|
req = self._make_request('/badpath')
|
||||||
req.remote_user = 'act:usr,act,AUTH_cfa'
|
req.remote_user = 'act:usr,act,AUTH_cfa'
|
||||||
resp = self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
@ -318,6 +341,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
req = self._make_request('/v1/AUTH_cfa/c')
|
req = self._make_request('/v1/AUTH_cfa/c')
|
||||||
resp = self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
req = self._make_request('/v1/AUTH_cfa/c')
|
req = self._make_request('/v1/AUTH_cfa/c')
|
||||||
req.acl = '.r:*,.rlistings'
|
req.acl = '.r:*,.rlistings'
|
||||||
self.assertEquals(self.test_auth.authorize(req), None)
|
self.assertEquals(self.test_auth.authorize(req), None)
|
||||||
@ -325,10 +350,14 @@ class TestAuth(unittest.TestCase):
|
|||||||
req.acl = '.r:*' # No listings allowed
|
req.acl = '.r:*' # No listings allowed
|
||||||
resp = self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
req = self._make_request('/v1/AUTH_cfa/c')
|
req = self._make_request('/v1/AUTH_cfa/c')
|
||||||
req.acl = '.r:.example.com,.rlistings'
|
req.acl = '.r:.example.com,.rlistings'
|
||||||
resp = self.test_auth.authorize(req)
|
resp = self.test_auth.authorize(req)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
req = self._make_request('/v1/AUTH_cfa/c')
|
req = self._make_request('/v1/AUTH_cfa/c')
|
||||||
req.referer = 'http://www.example.com/index.html'
|
req.referer = 'http://www.example.com/index.html'
|
||||||
req.acl = '.r:.example.com,.rlistings'
|
req.acl = '.r:.example.com,.rlistings'
|
||||||
@ -414,11 +443,16 @@ class TestAuth(unittest.TestCase):
|
|||||||
def test_get_token_fail(self):
|
def test_get_token_fail(self):
|
||||||
resp = self._make_request('/auth/v1.0').get_response(self.test_auth)
|
resp = self._make_request('/auth/v1.0').get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="unknown"')
|
||||||
resp = self._make_request(
|
resp = self._make_request(
|
||||||
'/auth/v1.0',
|
'/auth/v1.0',
|
||||||
headers={'X-Auth-User': 'act:usr',
|
headers={'X-Auth-User': 'act:usr',
|
||||||
'X-Auth-Key': 'key'}).get_response(self.test_auth)
|
'X-Auth-Key': 'key'}).get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="act"')
|
||||||
|
|
||||||
def test_get_token_fail_invalid_x_auth_user_format(self):
|
def test_get_token_fail_invalid_x_auth_user_format(self):
|
||||||
resp = self._make_request(
|
resp = self._make_request(
|
||||||
@ -426,6 +460,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
headers={'X-Auth-User': 'usr',
|
headers={'X-Auth-User': 'usr',
|
||||||
'X-Auth-Key': 'key'}).get_response(self.test_auth)
|
'X-Auth-Key': 'key'}).get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="act"')
|
||||||
|
|
||||||
def test_get_token_fail_non_matching_account_in_request(self):
|
def test_get_token_fail_non_matching_account_in_request(self):
|
||||||
resp = self._make_request(
|
resp = self._make_request(
|
||||||
@ -433,6 +469,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
headers={'X-Auth-User': 'act2:usr',
|
headers={'X-Auth-User': 'act2:usr',
|
||||||
'X-Auth-Key': 'key'}).get_response(self.test_auth)
|
'X-Auth-Key': 'key'}).get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="act"')
|
||||||
|
|
||||||
def test_get_token_fail_bad_path(self):
|
def test_get_token_fail_bad_path(self):
|
||||||
resp = self._make_request(
|
resp = self._make_request(
|
||||||
@ -446,6 +484,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
'/auth/v1/act/auth',
|
'/auth/v1/act/auth',
|
||||||
headers={'X-Auth-User': 'act:usr'}).get_response(self.test_auth)
|
headers={'X-Auth-User': 'act:usr'}).get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="act"')
|
||||||
|
|
||||||
def test_storage_url_default(self):
|
def test_storage_url_default(self):
|
||||||
self.test_auth = \
|
self.test_auth = \
|
||||||
@ -619,6 +659,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
req.remote_addr = '127.0.0.1'
|
req.remote_addr = '127.0.0.1'
|
||||||
resp = req.get_response(self.test_auth)
|
resp = req.get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
|
|
||||||
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
||||||
sync_key='othersecret')
|
sync_key='othersecret')
|
||||||
@ -630,6 +672,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
req.remote_addr = '127.0.0.1'
|
req.remote_addr = '127.0.0.1'
|
||||||
resp = req.get_response(self.test_auth)
|
resp = req.get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
|
|
||||||
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
||||||
sync_key=None)
|
sync_key=None)
|
||||||
@ -641,6 +685,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
req.remote_addr = '127.0.0.1'
|
req.remote_addr = '127.0.0.1'
|
||||||
resp = req.get_response(self.test_auth)
|
resp = req.get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
|
|
||||||
def test_sync_request_fail_no_timestamp(self):
|
def test_sync_request_fail_no_timestamp(self):
|
||||||
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
||||||
@ -652,6 +698,8 @@ class TestAuth(unittest.TestCase):
|
|||||||
req.remote_addr = '127.0.0.1'
|
req.remote_addr = '127.0.0.1'
|
||||||
resp = req.get_response(self.test_auth)
|
resp = req.get_response(self.test_auth)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="AUTH_cfa"')
|
||||||
|
|
||||||
def test_sync_request_success_lb_sync_host(self):
|
def test_sync_request_success_lb_sync_host(self):
|
||||||
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
self.test_auth.app = FakeApp(iter([('204 No Content', {}, '')]),
|
||||||
@ -696,6 +744,15 @@ class TestAuth(unittest.TestCase):
|
|||||||
groups = ath._get_user_groups('test', 'test:tester', 'AUTH_test')
|
groups = ath._get_user_groups('test', 'test:tester', 'AUTH_test')
|
||||||
self.assertEquals(groups, 'test,test:tester')
|
self.assertEquals(groups, 'test,test:tester')
|
||||||
|
|
||||||
|
def test_auth_scheme(self):
|
||||||
|
req = self._make_request('/v1/BLAH_account',
|
||||||
|
headers={'X-Auth-Token': 'BLAH_t'})
|
||||||
|
resp = req.get_response(self.test_auth)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals(resp.headers.get('Www-Authenticate'),
|
||||||
|
'Swift realm="BLAH_account"')
|
||||||
|
|
||||||
|
|
||||||
class TestParseUserCreation(unittest.TestCase):
|
class TestParseUserCreation(unittest.TestCase):
|
||||||
def test_parse_user_creation(self):
|
def test_parse_user_creation(self):
|
||||||
|
@ -214,6 +214,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_put_valid(self):
|
def test_put_valid(self):
|
||||||
method = 'PUT'
|
method = 'PUT'
|
||||||
@ -246,6 +247,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_missing_sig(self):
|
def test_missing_sig(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -260,6 +262,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_missing_expires(self):
|
def test_missing_expires(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -274,6 +277,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_bad_path(self):
|
def test_bad_path(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -289,6 +293,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_no_key(self):
|
def test_no_key(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -304,6 +309,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_head_allowed_by_get(self):
|
def test_head_allowed_by_get(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -356,6 +362,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
sig, expires)})
|
sig, expires)})
|
||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_post_not_allowed(self):
|
def test_post_not_allowed(self):
|
||||||
method = 'POST'
|
method = 'POST'
|
||||||
@ -372,6 +379,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_delete_not_allowed(self):
|
def test_delete_not_allowed(self):
|
||||||
method = 'DELETE'
|
method = 'DELETE'
|
||||||
@ -388,6 +396,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_delete_allowed_with_conf(self):
|
def test_delete_allowed_with_conf(self):
|
||||||
self.tempurl.methods.append('DELETE')
|
self.tempurl.methods.append('DELETE')
|
||||||
@ -420,6 +429,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_changed_path_invalid(self):
|
def test_changed_path_invalid(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -435,6 +445,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_changed_sig_invalid(self):
|
def test_changed_sig_invalid(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -454,6 +465,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_changed_expires_invalid(self):
|
def test_changed_expires_invalid(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -469,6 +481,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_different_key_invalid(self):
|
def test_different_key_invalid(self):
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -484,6 +497,7 @@ class TestTempURL(unittest.TestCase):
|
|||||||
resp = req.get_response(self.tempurl)
|
resp = req.get_response(self.tempurl)
|
||||||
self.assertEquals(resp.status_int, 401)
|
self.assertEquals(resp.status_int, 401)
|
||||||
self.assertTrue('Temp URL invalid' in resp.body)
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_removed_incoming_header(self):
|
def test_removed_incoming_header(self):
|
||||||
self.tempurl = tempurl.filter_factory({
|
self.tempurl = tempurl.filter_factory({
|
||||||
@ -653,6 +667,26 @@ class TestTempURL(unittest.TestCase):
|
|||||||
self.tempurl._invalid({'REQUEST_METHOD': 'HEAD'},
|
self.tempurl._invalid({'REQUEST_METHOD': 'HEAD'},
|
||||||
_start_response)))
|
_start_response)))
|
||||||
|
|
||||||
|
def test_auth_scheme_value(self):
|
||||||
|
# Passthrough
|
||||||
|
environ = {}
|
||||||
|
resp = self._make_request('/v1/a/c/o', environ=environ).get_response(
|
||||||
|
self.tempurl)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertTrue('Temp URL invalid' not in resp.body)
|
||||||
|
self.assertTrue('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertTrue('swift.auth_scheme' not in environ)
|
||||||
|
|
||||||
|
# Rejected by TempURL
|
||||||
|
req = self._make_request('/v1/a/c/o', keys=['abc'],
|
||||||
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
|
'QUERY_STRING':
|
||||||
|
'temp_url_sig=dummy&temp_url_expires=1234'})
|
||||||
|
resp = req.get_response(self.tempurl)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assertTrue('Temp URL invalid' in resp.body)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
def test_clean_incoming_headers(self):
|
def test_clean_incoming_headers(self):
|
||||||
irh = ''
|
irh = ''
|
||||||
iah = ''
|
iah = ''
|
||||||
|
@ -518,6 +518,101 @@ class TestRequest(unittest.TestCase):
|
|||||||
self.assertEquals(resp.status_int, 200)
|
self.assertEquals(resp.status_int, 200)
|
||||||
self.assertEquals(resp.body, 'hi')
|
self.assertEquals(resp.body, 'hi')
|
||||||
|
|
||||||
|
def test_401_unauthorized(self):
|
||||||
|
# No request environment
|
||||||
|
resp = swift.common.swob.HTTPUnauthorized()
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
# Request environment
|
||||||
|
req = swift.common.swob.Request.blank('/')
|
||||||
|
resp = swift.common.swob.HTTPUnauthorized(request=req)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
|
||||||
|
def test_401_valid_account_path(self):
|
||||||
|
|
||||||
|
def test_app(environ, start_response):
|
||||||
|
start_response('401 Unauthorized', [])
|
||||||
|
return ['hi']
|
||||||
|
|
||||||
|
# Request environment contains valid account in path
|
||||||
|
req = swift.common.swob.Request.blank('/v1/account-name')
|
||||||
|
resp = req.get_response(test_app)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals('Swift realm="account-name"',
|
||||||
|
resp.headers['Www-Authenticate'])
|
||||||
|
|
||||||
|
# Request environment contains valid account/container in path
|
||||||
|
req = swift.common.swob.Request.blank('/v1/account-name/c')
|
||||||
|
resp = req.get_response(test_app)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals('Swift realm="account-name"',
|
||||||
|
resp.headers['Www-Authenticate'])
|
||||||
|
|
||||||
|
def test_401_invalid_path(self):
|
||||||
|
|
||||||
|
def test_app(environ, start_response):
|
||||||
|
start_response('401 Unauthorized', [])
|
||||||
|
return ['hi']
|
||||||
|
|
||||||
|
# Request environment contains bad path
|
||||||
|
req = swift.common.swob.Request.blank('/random')
|
||||||
|
resp = req.get_response(test_app)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals('Swift realm="unknown"',
|
||||||
|
resp.headers['Www-Authenticate'])
|
||||||
|
|
||||||
|
def test_401_non_keystone_auth_path(self):
|
||||||
|
|
||||||
|
def test_app(environ, start_response):
|
||||||
|
start_response('401 Unauthorized', [])
|
||||||
|
return ['no creds in request']
|
||||||
|
|
||||||
|
# Request to get token
|
||||||
|
req = swift.common.swob.Request.blank('/v1.0/auth')
|
||||||
|
resp = req.get_response(test_app)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals('Swift realm="unknown"',
|
||||||
|
resp.headers['Www-Authenticate'])
|
||||||
|
|
||||||
|
# Other form of path
|
||||||
|
req = swift.common.swob.Request.blank('/auth/v1.0')
|
||||||
|
resp = req.get_response(test_app)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals('Swift realm="unknown"',
|
||||||
|
resp.headers['Www-Authenticate'])
|
||||||
|
|
||||||
|
def test_401_www_authenticate_exists(self):
|
||||||
|
|
||||||
|
def test_app(environ, start_response):
|
||||||
|
start_response('401 Unauthorized', {
|
||||||
|
'Www-Authenticate': 'Me realm="whatever"'})
|
||||||
|
return ['no creds in request']
|
||||||
|
|
||||||
|
# Auth middleware sets own Www-Authenticate
|
||||||
|
req = swift.common.swob.Request.blank('/auth/v1.0')
|
||||||
|
resp = req.get_response(test_app)
|
||||||
|
self.assertEquals(resp.status_int, 401)
|
||||||
|
self.assert_('Www-Authenticate' in resp.headers)
|
||||||
|
self.assertEquals('Me realm="whatever"',
|
||||||
|
resp.headers['Www-Authenticate'])
|
||||||
|
|
||||||
|
def test_not_401(self):
|
||||||
|
|
||||||
|
# Other status codes should not have WWW-Authenticate in response
|
||||||
|
def test_app(environ, start_response):
|
||||||
|
start_response('200 OK', [])
|
||||||
|
return ['hi']
|
||||||
|
|
||||||
|
req = swift.common.swob.Request.blank('/')
|
||||||
|
resp = req.get_response(test_app)
|
||||||
|
self.assert_('Www-Authenticate' not in resp.headers)
|
||||||
|
|
||||||
def test_properties(self):
|
def test_properties(self):
|
||||||
req = swift.common.swob.Request.blank('/hi/there', body='hi')
|
req = swift.common.swob.Request.blank('/hi/there', body='hi')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user