Merge "Add debugging info to SignatureDoesNotMatch responses"
This commit is contained in:
commit
ed18495faa
@ -375,6 +375,16 @@ class SigV4Mixin(object):
|
||||
'/'.join(self.scope),
|
||||
sha256(self._canonical_request()).hexdigest()])
|
||||
|
||||
def signature_does_not_match_kwargs(self):
|
||||
kwargs = super(SigV4Mixin, self).signature_does_not_match_kwargs()
|
||||
cr = self._canonical_request()
|
||||
kwargs.update({
|
||||
'canonical_request': cr,
|
||||
'canonical_request_bytes': ' '.join(
|
||||
format(ord(c), '02x') for c in cr),
|
||||
})
|
||||
return kwargs
|
||||
|
||||
|
||||
def get_request_class(env, s3_acl):
|
||||
"""
|
||||
@ -875,6 +885,15 @@ class S3Request(swob.Request):
|
||||
buf.append(path)
|
||||
return '\n'.join(buf)
|
||||
|
||||
def signature_does_not_match_kwargs(self):
|
||||
return {
|
||||
'a_w_s_access_key_id': self.access_key,
|
||||
'string_to_sign': self.string_to_sign,
|
||||
'signature_provided': self.signature,
|
||||
'string_to_sign_bytes': ' '.join(
|
||||
format(ord(c), '02x') for c in self.string_to_sign),
|
||||
}
|
||||
|
||||
@property
|
||||
def controller_name(self):
|
||||
return self.controller.__name__[:-len('Controller')]
|
||||
@ -1211,7 +1230,8 @@ class S3Request(swob.Request):
|
||||
if status == HTTP_BAD_REQUEST:
|
||||
raise BadSwiftRequest(err_msg)
|
||||
if status == HTTP_UNAUTHORIZED:
|
||||
raise SignatureDoesNotMatch()
|
||||
raise SignatureDoesNotMatch(
|
||||
**self.signature_does_not_match_kwargs())
|
||||
if status == HTTP_FORBIDDEN:
|
||||
raise AccessDenied()
|
||||
|
||||
@ -1334,7 +1354,8 @@ class S3AclRequest(S3Request):
|
||||
sw_resp = sw_req.get_response(app)
|
||||
|
||||
if not sw_req.remote_user:
|
||||
raise SignatureDoesNotMatch()
|
||||
raise SignatureDoesNotMatch(
|
||||
**self.signature_does_not_match_kwargs())
|
||||
|
||||
_, self.account, _ = split_path(sw_resp.environ['PATH_INFO'],
|
||||
2, 3, True)
|
||||
|
@ -107,7 +107,7 @@ class S3ApiTestCase(unittest.TestCase):
|
||||
return elem.find('./Message').text
|
||||
|
||||
def _test_method_error(self, method, path, response_class, headers={},
|
||||
env={}):
|
||||
env={}, expected_xml_tags=None):
|
||||
if not path.startswith('/'):
|
||||
path = '/' + path # add a missing slash before the path
|
||||
|
||||
@ -121,6 +121,10 @@ class S3ApiTestCase(unittest.TestCase):
|
||||
env.update({'REQUEST_METHOD': method})
|
||||
req = swob.Request.blank(path, environ=env, headers=headers)
|
||||
status, headers, body = self.call_s3api(req)
|
||||
if expected_xml_tags is not None:
|
||||
elem = fromstring(body, 'Error')
|
||||
self.assertEqual(set(expected_xml_tags),
|
||||
{x.tag for x in elem})
|
||||
return self._get_error_code(body)
|
||||
|
||||
def get_date_header(self):
|
||||
|
@ -35,6 +35,7 @@ class FakeSwift(object):
|
||||
# mapping of (method, path) --> (response class, headers, body)
|
||||
self._responses = {}
|
||||
self.s3_acl = s3_acl
|
||||
self.remote_user = 'authorized'
|
||||
|
||||
def _fake_auth_middleware(self, env):
|
||||
if 'swift.authorize_override' in env:
|
||||
@ -50,7 +51,8 @@ class FakeSwift(object):
|
||||
path = env['PATH_INFO']
|
||||
env['PATH_INFO'] = path.replace(tenant_user, 'AUTH_' + tenant)
|
||||
|
||||
env['REMOTE_USER'] = 'authorized'
|
||||
if self.remote_user:
|
||||
env['REMOTE_USER'] = self.remote_user
|
||||
|
||||
if env['REQUEST_METHOD'] == 'TEST':
|
||||
|
||||
|
@ -306,6 +306,17 @@ class TestS3ApiObj(S3ApiTestCase):
|
||||
def test_object_GET(self):
|
||||
self._test_object_GETorHEAD('GET')
|
||||
|
||||
@s3acl(s3acl_only=True)
|
||||
def test_object_GET_with_s3acl_and_unknown_user(self):
|
||||
self.swift.remote_user = None
|
||||
req = Request.blank('/bucket/object',
|
||||
environ={'REQUEST_METHOD': 'GET'},
|
||||
headers={'Authorization': 'AWS test:tester:hmac',
|
||||
'Date': self.get_date_header()})
|
||||
status, headers, body = self.call_s3api(req)
|
||||
self.assertEqual(status, '403 Forbidden')
|
||||
self.assertEqual(self._get_error_code(body), 'SignatureDoesNotMatch')
|
||||
|
||||
@s3acl(s3acl_only=True)
|
||||
def test_object_GET_with_s3acl_and_keystone(self):
|
||||
# for passing keystone authentication root
|
||||
|
@ -50,7 +50,10 @@ class TestS3ApiService(S3ApiTestCase):
|
||||
self.setup_buckets()
|
||||
|
||||
def test_service_GET_error(self):
|
||||
code = self._test_method_error('GET', '', swob.HTTPUnauthorized)
|
||||
code = self._test_method_error(
|
||||
'GET', '', swob.HTTPUnauthorized, expected_xml_tags=(
|
||||
'Code', 'Message', 'AWSAccessKeyId', 'StringToSign',
|
||||
'StringToSignBytes', 'SignatureProvided'))
|
||||
self.assertEqual(code, 'SignatureDoesNotMatch')
|
||||
code = self._test_method_error('GET', '', swob.HTTPForbidden)
|
||||
self.assertEqual(code, 'AccessDenied')
|
||||
|
Loading…
Reference in New Issue
Block a user