Merge "crypto - refactor footers callback" into feature/crypto
This commit is contained in:
commit
d420d03273
|
@ -89,36 +89,15 @@ class EncInputWrapper(object):
|
|||
path_ver, path_for_base = req.split_path(1, 2, True)
|
||||
|
||||
def footers_callback(footers):
|
||||
plaintext_etag = None
|
||||
if self.body_crypto_ctxt:
|
||||
plaintext_etag = self.plaintext_md5.hexdigest()
|
||||
# Encrypt the plaintext etag using the container key and
|
||||
# persist as sysmeta along with the crypto parameters
|
||||
# that were used.
|
||||
|
||||
val, etag_crypto_meta = encrypt_header_val(
|
||||
self.crypto, plaintext_etag,
|
||||
self.keys['container'],
|
||||
iv_base=os.path.join(os.sep, path_for_base))
|
||||
footers['X-Object-Sysmeta-Crypto-Etag'] = val
|
||||
footers['X-Object-Sysmeta-Crypto-Meta-Etag'] = \
|
||||
dump_crypto_meta(etag_crypto_meta)
|
||||
footers['X-Object-Sysmeta-Crypto-Meta'] = dump_crypto_meta(
|
||||
self.body_crypto_meta)
|
||||
else:
|
||||
# No data was read from body, nothing was encrypted, so
|
||||
# don't set any crypto sysmeta for the body, but do re-instate
|
||||
# any etag provided in inbound request.
|
||||
if client_etag is not None:
|
||||
footers['Etag'] = client_etag
|
||||
|
||||
if inner_callback:
|
||||
# pass on footers dict to any other callback that was
|
||||
# registered before this one. It may override any footers that
|
||||
# were set.
|
||||
inner_callback(footers)
|
||||
|
||||
plaintext_etag = encrypted_etag = etag_crypto_meta = None
|
||||
if self.body_crypto_ctxt:
|
||||
plaintext_etag = self.plaintext_md5.hexdigest()
|
||||
# If client (or other middleware) supplied etag, then validate
|
||||
# against plaintext etag
|
||||
etag_to_check = footers.get('Etag') or client_etag
|
||||
|
@ -129,6 +108,26 @@ class EncInputWrapper(object):
|
|||
# override any previous notion of etag with the ciphertext etag
|
||||
footers['Etag'] = self.ciphertext_md5.hexdigest()
|
||||
|
||||
# Encrypt the plaintext etag using the container key and
|
||||
# persist as sysmeta along with the crypto parameters
|
||||
# that were used.
|
||||
encrypted_etag, etag_crypto_meta = encrypt_header_val(
|
||||
self.crypto, plaintext_etag,
|
||||
self.keys['container'],
|
||||
iv_base=os.path.join(os.sep, path_for_base))
|
||||
footers['X-Object-Sysmeta-Crypto-Etag'] = encrypted_etag
|
||||
footers['X-Object-Sysmeta-Crypto-Meta-Etag'] = \
|
||||
dump_crypto_meta(etag_crypto_meta)
|
||||
footers['X-Object-Sysmeta-Crypto-Meta'] = dump_crypto_meta(
|
||||
self.body_crypto_meta)
|
||||
else:
|
||||
# No data was read from body, nothing was encrypted, so don't
|
||||
# set any crypto sysmeta for the body, but do re-instate any
|
||||
# etag provided in inbound request if other middleware has not
|
||||
# already set a value.
|
||||
if client_etag is not None:
|
||||
footers.setdefault('Etag', client_etag)
|
||||
|
||||
# When deciding on the etag that should appear in container
|
||||
# listings, look for:
|
||||
# * override in the footer, otherwise
|
||||
|
@ -137,7 +136,7 @@ class EncInputWrapper(object):
|
|||
# This may be None if no override was set and no data was read
|
||||
container_listing_etag = footers.get(
|
||||
'X-Object-Sysmeta-Container-Update-Override-Etag',
|
||||
container_listing_etag_header or plaintext_etag)
|
||||
container_listing_etag_header)
|
||||
|
||||
if container_listing_etag is not None:
|
||||
# Encrypt the container-listing etag using the container key
|
||||
|
@ -150,6 +149,13 @@ class EncInputWrapper(object):
|
|||
crypto_meta['key_id'] = self.keys['id']
|
||||
footers['X-Object-Sysmeta-Container-Update-Override-Etag'] = \
|
||||
append_crypto_meta(val, crypto_meta)
|
||||
elif plaintext_etag is not None:
|
||||
# use the same encrypted etag value stored in object sysmeta,
|
||||
# with its crypto parameters appended
|
||||
etag_crypto_meta['key_id'] = self.keys['id']
|
||||
footers['X-Object-Sysmeta-Container-Update-Override-Etag'] = \
|
||||
append_crypto_meta(encrypted_etag, etag_crypto_meta)
|
||||
# else: no override was set and no data was read
|
||||
|
||||
req.environ['swift.callback.update_footers'] = footers_callback
|
||||
|
||||
|
|
|
@ -456,8 +456,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
|
||||
hdrs = {'x-object-meta-test': 'encrypt me',
|
||||
'x-object-sysmeta-test': 'do not encrypt me'}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
key = fetch_crypto_keys()['object']
|
||||
self.app.register('POST', '/v1/a/c/o', HTTPAccepted, {})
|
||||
resp = req.get_response(self.encrypter)
|
||||
|
@ -582,8 +581,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
|
||||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body))}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPCreated,
|
||||
{'Etag': 'ciphertextEtag'})
|
||||
resp = req.get_response(self.encrypter)
|
||||
|
@ -599,8 +597,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
'wsgi.input': FileLikeIter(chunks)}
|
||||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body))}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, headers=hdrs)
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})
|
||||
|
||||
with mock.patch(
|
||||
|
@ -624,8 +621,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body)),
|
||||
'Etag': md5hex(body)}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, headers=hdrs)
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})
|
||||
|
||||
with mock.patch(
|
||||
|
@ -648,8 +644,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body)),
|
||||
'Etag': 'badclientetag'}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, headers=hdrs)
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})
|
||||
resp = req.get_response(self.encrypter)
|
||||
self.assertEqual('422 Unprocessable Entity', resp.status)
|
||||
|
@ -659,8 +654,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
env = {'REQUEST_METHOD': 'PUT'}
|
||||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body))}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
resp = req.get_response(self.encrypter)
|
||||
self.assertEqual('500 Internal Error', resp.status)
|
||||
self.assertIn('%s not in env' % CRYPTO_KEY_CALLBACK,
|
||||
|
@ -676,8 +670,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
CRYPTO_KEY_CALLBACK: raise_exc}
|
||||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body))}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
resp = req.get_response(self.encrypter)
|
||||
self.assertEqual('500 Internal Error', resp.status)
|
||||
self.assertIn('from %s: Testing' % CRYPTO_KEY_CALLBACK,
|
||||
|
@ -699,8 +692,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
lambda footers: footers.update(other_footers)}
|
||||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body))}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPCreated, {})
|
||||
resp = req.get_response(self.encrypter)
|
||||
self.assertEqual('201 Created', resp.status)
|
||||
|
@ -721,8 +713,7 @@ class TestEncrypter(unittest.TestCase):
|
|||
CRYPTO_KEY_CALLBACK: fetch_crypto_keys}
|
||||
hdrs = {'content-type': 'text/plain',
|
||||
'content-length': str(len(body))}
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
req = Request.blank('/v1/a/c/o', environ=env, body=body, headers=hdrs)
|
||||
mocked_func = 'swift.common.middleware.encrypter.check_metadata'
|
||||
with mock.patch(mocked_func) as mocked:
|
||||
mocked.side_effect = [HTTPBadRequest('testing')]
|
||||
|
|
Loading…
Reference in New Issue