From cfba1c1ba8f3659e6de727c3f1c274052e9ccace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Douglas=20Mendiz=C3=A1bal?= Date: Thu, 13 Feb 2025 16:42:26 -0500 Subject: [PATCH] Use MultiFernet to enable more than one KEK This patch changes the `kek` option for the Simple Crypto Plugin to allow more than one KEK to be specified. When more than one KEK is configured, the first KEK is used to encrypt new data and any additiona KEKs are only used to decrypt existing data. This change allows for rotating in new KEKs on demand. Change-Id: I0c3683e316e78478461f5f30f4f353ff43a3bb09 --- barbican/plugin/crypto/simple_crypto.py | 21 ++++++++++++------- barbican/tests/plugin/crypto/test_crypto.py | 2 +- ...-crypto-multiple-kek-939d7fae5657ca8e.yaml | 18 ++++++++++++++++ 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/simple-crypto-multiple-kek-939d7fae5657ca8e.yaml 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=