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