diff --git a/barbican/plugin/crypto/simple_crypto.py b/barbican/plugin/crypto/simple_crypto.py index 7c3f8d7cc..964ef86e6 100644 --- a/barbican/plugin/crypto/simple_crypto.py +++ b/barbican/plugin/crypto/simple_crypto.py @@ -32,10 +32,13 @@ LOG = utils.getLogger(__name__) simple_crypto_plugin_group = cfg.OptGroup(name='simple_crypto_plugin', title="Simple Crypto Plugin Options") simple_crypto_plugin_opts = [ - cfg.StrOpt('kek', - default='dGhpcnR5X3R3b19ieXRlX2tleWJsYWhibGFoYmxhaGg=', - help=u._('Key encryption key to be used by Simple Crypto ' - 'Plugin'), secret=True), + cfg.MultiStrOpt( + 'kek', + default=['dGhpcnR5X3R3b19ieXRlX2tleWJsYWhibGFoYmxhaGg='], + secret=True, + help=u._('Fernet Key-Encryption Key (KEK) to be used by SimpleCrypto ' + 'Plugin to encrypt Project-specific KEKs.'), + ), cfg.StrOpt('plugin_name', help=u._('User friendly plugin name'), default='Software Only Crypto'), @@ -53,7 +56,9 @@ class SimpleCryptoPlugin(c.CryptoPluginBase): """Insecure implementation of the crypto plugin.""" def __init__(self, conf=CONF): - self.master_kek = conf.simple_crypto_plugin.kek + if len(conf.simple_crypto_plugin.kek) < 1: + raise ValueError(u._("SimpleCrypto KEK is undefined")) + self.master_keys = conf.simple_crypto_plugin.kek self.plugin_name = conf.simple_crypto_plugin.plugin_name LOG.info("{} initialized".format(self.plugin_name)) @@ -64,7 +69,9 @@ class SimpleCryptoPlugin(c.CryptoPluginBase): if not kek_meta_dto.plugin_meta: raise ValueError(u._('KEK not yet created.')) # the kek is stored encrypted. Need to decrypt. - encryptor = fernet.Fernet(self.master_kek) + encryptor = fernet.MultiFernet( + [fernet.Fernet(x) for x in self.master_keys] + ) # Note : If plugin_meta type is unicode, encode to byte. if isinstance(kek_meta_dto.plugin_meta, str): kek_meta_dto.plugin_meta = kek_meta_dto.plugin_meta.encode('utf-8') @@ -100,7 +107,7 @@ class SimpleCryptoPlugin(c.CryptoPluginBase): kek_meta_dto.mode = 'cbc' if not kek_meta_dto.plugin_meta: # the kek is stored encrypted in the plugin_meta field - encryptor = fernet.Fernet(self.master_kek) + encryptor = fernet.Fernet(self.master_keys[0]) key = fernet.Fernet.generate_key() kek_meta_dto.plugin_meta = encryptor.encrypt(key) return kek_meta_dto diff --git a/barbican/tests/plugin/crypto/test_crypto.py b/barbican/tests/plugin/crypto/test_crypto.py index ebb423c75..c62e05c6a 100644 --- a/barbican/tests/plugin/crypto/test_crypto.py +++ b/barbican/tests/plugin/crypto/test_crypto.py @@ -65,7 +65,7 @@ class WhenTestingSimpleCryptoPlugin(utils.BaseTestCase): Compare with unencrypted """ project_kek = fernet.Fernet.generate_key() - encryptor = fernet.Fernet(self.plugin.master_kek) + encryptor = fernet.Fernet(self.plugin.master_keys[0]) ENC_project_kek = encryptor.encrypt(project_kek) UENC_project_kek = ENC_project_kek kek_meta_dto = self._get_mocked_kek_meta_dto() diff --git a/releasenotes/notes/simple-crypto-multiple-kek-939d7fae5657ca8e.yaml b/releasenotes/notes/simple-crypto-multiple-kek-939d7fae5657ca8e.yaml new file mode 100644 index 000000000..a8eed0ed4 --- /dev/null +++ b/releasenotes/notes/simple-crypto-multiple-kek-939d7fae5657ca8e.yaml @@ -0,0 +1,18 @@ +--- +security: + - | + The configuration for Simple Crypto Plugin has been updated to allow more + than one Key-Encryption-Key (KEK) to be defined. This enables the ability + to rotate in new KEKs on demand. If there is more than one KEK specified + in the config file, then the first KEK is considered "active", which means + it will be used to encrypt any new Project-specific KEKs. Any additional + KEKs will only be used to decrypt existing pKEKs when necessary. .e.g. + + .. code-block:: + + [simple_crypto_plugin] + # First key is used for ecnrypting new data + kek = Yl1EKQ5e4VpK3X7lbWF249GDsk0mrL929P-Mnnz-bdc= + # Additionak keys used for decrypting existing data + kek = AfXmy1NEfzmtJEYVGrQJ0C2-dr8S0lFoNBX5Vb7MC44= + kek = Ua4Y8ryfamShYT_TzxSjok9Tl11OWFSk3whOSY-TIaw=