Files
swift/test/unit/common/middleware/crypto/crypto_helpers.py
Alistair Coles 2722e49a8c Add support for multiple root encryption secrets
For some use cases operators would like to periodically introduce a
new encryption root secret that would be used when new object data is
written. However, existing encrypted data does not need to be
re-encrypted with keys derived from the new root secret. Older root
secret(s) would still be used as necessary to decrypt older object
data.

This patch modifies the KeyMaster class to support multiple root
secrets indexed via unique secret_id's, and to store the id of the
root secret used for an encryption operation in the crypto meta. The
decrypter is modified to fetch appropriate keys based on the secret id
in retrieved crypto meta.

The changes are backwards compatible with previous crypto middleware
configurations and existing encrypted object data.

Change-Id: I40307acf39b6c1cc9921f711a8da55d03924d232
2018-08-17 17:54:30 +00:00

74 lines
2.5 KiB
Python

# Copyright (c) 2015-2016 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import base64
import hashlib
from swift.common.exceptions import UnknownSecretIdError
from swift.common.middleware.crypto.crypto_utils import Crypto
def fetch_crypto_keys(key_id=None):
id_to_keys = {None: {'account': 'This is an account key 012345678',
'container': 'This is a container key 01234567',
'object': 'This is an object key 0123456789'},
'myid': {'account': 'This is an account key 123456789',
'container': 'This is a container key 12345678',
'object': 'This is an object key 1234567890'}}
key_id = key_id or {}
secret_id = key_id.get('secret_id') or None
try:
keys = dict(id_to_keys[secret_id])
except KeyError:
raise UnknownSecretIdError(secret_id)
keys['id'] = {'v': 'fake', 'path': '/a/c/fake'}
if secret_id:
keys['id']['secret_id'] = secret_id
keys['all_ids'] = [{'v': 'fake', 'path': '/a/c/fake'},
{'v': 'fake', 'path': '/a/c/fake', 'secret_id': 'myid'}]
return keys
def md5hex(s):
return hashlib.md5(s).hexdigest()
def encrypt(val, key=None, iv=None, ctxt=None):
if ctxt is None:
ctxt = Crypto({}).create_encryption_ctxt(key, iv)
enc_val = ctxt.update(val)
return enc_val
def decrypt(key, iv, enc_val):
dec_ctxt = Crypto({}).create_decryption_ctxt(key, iv, 0)
dec_val = dec_ctxt.update(enc_val)
return dec_val
FAKE_IV = "This is an IV123"
# do not use this example encryption_root_secret in production, use a randomly
# generated value with high entropy
TEST_KEYMASTER_CONF = {
'encryption_root_secret': base64.b64encode(b'x' * 32),
'encryption_root_secret_1': base64.b64encode(b'y' * 32),
'encryption_root_secret_2': base64.b64encode(b'z' * 32)
}
def fake_get_crypto_meta(**kwargs):
meta = {'iv': FAKE_IV, 'cipher': Crypto.cipher}
meta.update(kwargs)
return meta