encryptors: Introduce encryption provider constants

These constants detail the supported encryption formats and their
associated in tree encryption provider implementations.

The use of out of tree and direct use of these in tree implementations
is now deprecated and will be blocked in the Pike release of os-brick.

Change-Id: Ic155bd29d46059832cce970bf60375e7e472eca6
Partial-bug: #1639293
This commit is contained in:
Lee Yarwood 2017-01-04 17:16:05 +00:00
parent 5023c921f0
commit 916cfafae3
3 changed files with 133 additions and 42 deletions

View File

@ -22,6 +22,23 @@ from oslo_utils import strutils
LOG = logging.getLogger(__name__)
LUKS = "luks"
PLAIN = "plain"
FORMAT_TO_FRONTEND_ENCRYPTOR_MAP = {
LUKS: 'os_brick.encryptors.luks.LuksEncryptor',
PLAIN: 'os_brick.encryptors.cryptsetup.CryptsetupEncryptor'
}
LEGACY_PROVIDER_CLASS_TO_FORMAT_MAP = {
"os_brick.encryptors.luks.LuksEncryptor": LUKS,
"os_brick.encryptors.cryptsetup.CryptsetupEncryptor": PLAIN,
"os_brick.encryptors.nop.NoopEncryptor": None,
"LuksEncryptor": LUKS,
"CryptsetupEncryptor": PLAIN,
"NoOpEncryptor": None,
}
def get_volume_encryptor(root_helper,
connection_info,
@ -43,14 +60,24 @@ def get_volume_encryptor(root_helper,
if location and location.lower() == 'front-end': # case insensitive
provider = kwargs.get('provider')
if provider == 'LuksEncryptor' or 'LuksEncryptor' in provider:
provider = 'os_brick.encryptors.luks.LuksEncryptor'
elif (provider == 'CryptsetupEncryptor' or
'CryptsetupEncryptor' in provider):
provider = \
'os_brick.encryptors.cryptsetup.CryptsetupEncryptor'
elif (provider == 'NoOpEncryptor' or 'NoOpEncryptor' in provider):
provider = 'os_brick.encryptors.nop.NoOpEncryptor'
# TODO(lyarwood): Remove the following in Pike and raise an
# ERROR if provider is not a key in SUPPORTED_ENCRYPTION_PROVIDERS.
# Until then continue to allow both the class name and path to be used.
if provider in LEGACY_PROVIDER_CLASS_TO_FORMAT_MAP:
LOG.warning(_LW("Use of the in tree encryptor class %(provider)s"
" by directly referencing the implementation class"
" will be blocked in the Pike release of"
" os-brick."), {'provider': provider})
provider = LEGACY_PROVIDER_CLASS_TO_FORMAT_MAP[provider]
if provider in FORMAT_TO_FRONTEND_ENCRYPTOR_MAP:
provider = FORMAT_TO_FRONTEND_ENCRYPTOR_MAP[provider]
elif provider is None:
provider = "os_brick.encryptors.nop.NoOpEncryptor"
else:
LOG.warning(_LW("Use of the out of tree encryptor class "
"%(provider)s will be blocked with the Pike "
"release of os-brick."), {'provider': provider})
try:
encryptor = importutils.import_object(

View File

@ -40,44 +40,42 @@ class VolumeEncryptorTestCase(base.TestCase):
class BaseEncryptorTestCase(VolumeEncryptorTestCase):
def _test_get_encryptor(self, provider, expected_provider_class):
encryption = {'control_location': 'front-end',
'provider': provider}
encryptor = encryptors.get_volume_encryptor(
root_helper=self.root_helper,
connection_info=self.connection_info,
keymgr=self.keymgr,
**encryption)
self.assertIsInstance(encryptor, expected_provider_class)
def test_get_encryptors(self):
encryption = {'control_location': 'front-end',
'provider': 'LuksEncryptor'}
encryptor = encryptors.get_volume_encryptor(
root_helper=self.root_helper,
connection_info=self.connection_info,
keymgr=self.keymgr,
**encryption)
self._test_get_encryptor('luks',
encryptors.luks.LuksEncryptor)
# TODO(lyarwood): Remove the following in Pike
self._test_get_encryptor('LuksEncryptor',
encryptors.luks.LuksEncryptor)
self._test_get_encryptor('os_brick.encryptors.luks.LuksEncryptor',
encryptors.luks.LuksEncryptor)
self.assertIsInstance(encryptor,
encryptors.luks.LuksEncryptor,
"encryptor is not an instance of LuksEncryptor")
self._test_get_encryptor('plain',
encryptors.cryptsetup.CryptsetupEncryptor)
# TODO(lyarwood): Remove the following in Pike
self._test_get_encryptor('CryptsetupEncryptor',
encryptors.cryptsetup.CryptsetupEncryptor)
self._test_get_encryptor(
'os_brick.encryptors.cryptsetup.CryptsetupEncryptor',
encryptors.cryptsetup.CryptsetupEncryptor)
encryption = {'control_location': 'front-end',
'provider': 'CryptsetupEncryptor'}
encryptor = encryptors.get_volume_encryptor(
root_helper=self.root_helper,
connection_info=self.connection_info,
keymgr=self.keymgr,
**encryption)
self.assertIsInstance(encryptor,
encryptors.cryptsetup.CryptsetupEncryptor,
"encryptor is not an instance of"
"CryptsetupEncryptor")
encryption = {'control_location': 'front-end',
'provider': 'NoOpEncryptor'}
encryptor = encryptors.get_volume_encryptor(
root_helper=self.root_helper,
connection_info=self.connection_info,
keymgr=self.keymgr,
**encryption)
self.assertIsInstance(encryptor,
encryptors.nop.NoOpEncryptor,
"encryptor is not an instance of NoOpEncryptor")
self._test_get_encryptor(None,
encryptors.nop.NoOpEncryptor)
# TODO(lyarwood): Remove the following in Pike
self._test_get_encryptor('NoOpEncryptor',
encryptors.nop.NoOpEncryptor)
self._test_get_encryptor('os_brick.encryptors.nop.NoOpEncryptor',
encryptors.nop.NoOpEncryptor)
def test_get_error_encryptors(self):
encryption = {'control_location': 'front-end',
@ -106,3 +104,55 @@ class BaseEncryptorTestCase(VolumeEncryptorTestCase):
"%(exception)s",
{'provider': provider,
'exception': e})
@mock.patch('os_brick.encryptors.LOG')
def test_get_missing_out_of_tree_encryptor_log(self, log):
provider = 'TestEncryptor'
encryption = {'control_location': 'front-end',
'provider': provider}
try:
encryptors.get_volume_encryptor(
root_helper=self.root_helper,
connection_info=self.connection_info,
keymgr=self.keymgr,
**encryption)
except Exception as e:
log.error.assert_called_once_with("Error instantiating "
"%(provider)s: "
"%(exception)s",
{'provider': provider,
'exception': e})
log.warning.assert_called_once_with("Use of the out of tree "
"encryptor class %(provider)s "
"will be blocked with the "
"Pike release of os-brick.",
{'provider': provider})
@mock.patch('os_brick.encryptors.LOG')
def test_get_direct_encryptor_log(self, log):
encryption = {'control_location': 'front-end',
'provider': 'LuksEncryptor'}
encryptors.get_volume_encryptor(
root_helper=self.root_helper,
connection_info=self.connection_info,
keymgr=self.keymgr,
**encryption)
encryption = {'control_location': 'front-end',
'provider': 'os_brick.encryptors.luks.LuksEncryptor'}
encryptors.get_volume_encryptor(
root_helper=self.root_helper,
connection_info=self.connection_info,
keymgr=self.keymgr,
**encryption)
log.warning.assert_has_calls([
mock.call("Use of the in tree encryptor class %(provider)s by "
"directly referencing the implementation class will be "
"blocked in the Pike release of os-brick.",
{'provider': 'LuksEncryptor'}),
mock.call("Use of the in tree encryptor class %(provider)s by "
"directly referencing the implementation class will be "
"blocked in the Pike release of os-brick.",
{'provider':
'os_brick.encryptors.luks.LuksEncryptor'})])

View File

@ -0,0 +1,14 @@
---
features:
- |
Encryption provider constants have been introduced detailing the supported
encryption formats such as LUKs along with their associated in-tree
provider implementations. These constants should now be used to identify an
encryption provider implementation for a given encryption format.
deprecations:
- |
The direct use of the encryption provider classes such as
os_brick.encryptors.luks.LuksEncryptor is now deprecated and will be
blocked in the Pike release of os-brick. The use of out of tree encryption
provider classes is also deprecated and will be blocked in the Pike release
of os-brick.