diff options
author | Dan Prince <dprince@redhat.com> | 2013-09-12 11:14:30 -0400 |
---|---|---|
committer | Dan Prince <dprince@redhat.com> | 2013-09-13 07:08:16 -0400 |
commit | a0d785868c859fcd016bbcfb033340e187721054 (patch) | |
tree | 3d757638bb05363e7818eb2f8a64df46fdfb2997 /nova/keymgr | |
parent | 2f6022f6bff9172a075b01c6cb6f87a4b4aabeb8 (diff) | |
download | nova-a0d785868c859fcd016bbcfb033340e187721054.tar.gz |
Move required keymgr classes out of nova/tests
Currently the Nova default keymgr implementation tries to
import classes from nova/tests. This could be a very bad
thing for production deployments which may not include
code from nova/tests.
This change moves two required modules (single_key_mgr and
mock_key_mgr) into the nova/keymgr tree.
Fixes bug: #1224526
Change-Id: I683b0245ab6b6acf8a4ba26f96d8c505f7c7cac8
Diffstat (limited to 'nova/keymgr')
-rw-r--r-- | nova/keymgr/conf_key_mgr.py | 2 | ||||
-rw-r--r-- | nova/keymgr/mock_key_mgr.py | 139 | ||||
-rw-r--r-- | nova/keymgr/single_key_mgr.py | 73 |
3 files changed, 213 insertions, 1 deletions
diff --git a/nova/keymgr/conf_key_mgr.py b/nova/keymgr/conf_key_mgr.py index 1240cb487b..b327317541 100644 --- a/nova/keymgr/conf_key_mgr.py +++ b/nova/keymgr/conf_key_mgr.py @@ -34,8 +34,8 @@ encryption key so *any* volume can be decrypted once the fixed key is known. from oslo.config import cfg +from nova.keymgr import single_key_mgr from nova.openstack.common.gettextutils import _ -from nova.tests.keymgr import single_key_mgr key_mgr_opts = [ cfg.StrOpt('fixed_key', diff --git a/nova/keymgr/mock_key_mgr.py b/nova/keymgr/mock_key_mgr.py new file mode 100644 index 0000000000..5a0f8c21d6 --- /dev/null +++ b/nova/keymgr/mock_key_mgr.py @@ -0,0 +1,139 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2013 The Johns Hopkins University/Applied Physics Laboratory +# All Rights Reserved. +# +# 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. + +""" +A mock implementation of a key manager that stores keys in a dictionary. + +This key manager implementation is primarily intended for testing. In +particular, it does not store keys persistently. Lack of a centralized key +store also makes this implementation unsuitable for use among different +services. + +Note: Instantiating this class multiple times will create separate key stores. +Keys created in one instance will not be accessible from other instances of +this class. +""" + +import array + +from nova import exception +from nova.keymgr import key +from nova.keymgr import key_mgr +from nova.openstack.common.gettextutils import _ +from nova.openstack.common import log as logging +from nova.openstack.common import uuidutils +from nova import utils + + +LOG = logging.getLogger(__name__) + + +class MockKeyManager(key_mgr.KeyManager): + """ + This mock key manager implementation supports all the methods specified + by the key manager interface. This implementation stores keys within a + dictionary, and as a result, it is not acceptable for use across different + services. Side effects (e.g., raising exceptions) for each method are + handled as specified by the key manager interface. + + This key manager is not suitable for use in production deployments. + """ + + def __init__(self): + LOG.warn(_('This key manager is not suitable for use in production' + ' deployments')) + + self.keys = {} + + def _generate_hex_key(self, **kwargs): + key_length = kwargs.get('key_length', 256) + # hex digit => 4 bits + hex_encoded = utils.generate_password(length=key_length / 4, + symbolgroups='0123456789ABCDEF') + return hex_encoded + + def _generate_key(self, **kwargs): + _hex = self._generate_hex_key(**kwargs) + return key.SymmetricKey('AES', + array.array('B', _hex.decode('hex')).tolist()) + + def create_key(self, ctxt, **kwargs): + """Creates a key. + + This implementation returns a UUID for the created key. A + NotAuthorized exception is raised if the specified context is None. + """ + if ctxt is None: + raise exception.NotAuthorized() + + key = self._generate_key(**kwargs) + return self.store_key(ctxt, key) + + def _generate_key_id(self): + key_id = uuidutils.generate_uuid() + while key_id in self.keys: + key_id = uuidutils.generate_uuid() + + return key_id + + def _generate_key_id(self): + key_id = uuidutils.generate_uuid() + while key_id in self.keys: + key_id = uuidutils.generate_uuid() + + return key_id + + def store_key(self, ctxt, key, **kwargs): + """Stores (i.e., registers) a key with the key manager.""" + if ctxt is None: + raise exception.NotAuthorized() + + key_id = self._generate_key_id() + self.keys[key_id] = key + + return key_id + + def copy_key(self, ctxt, key_id, **kwargs): + if ctxt is None: + raise exception.NotAuthorized() + + copied_key_id = self._generate_key_id() + self.keys[copied_key_id] = self.keys[key_id] + + return copied_key_id + + def get_key(self, ctxt, key_id, **kwargs): + """Retrieves the key identified by the specified id. + + This implementation returns the key that is associated with the + specified UUID. A NotAuthorized exception is raised if the specified + context is None; a KeyError is raised if the UUID is invalid. + """ + if ctxt is None: + raise exception.NotAuthorized() + + return self.keys[key_id] + + def delete_key(self, ctxt, key_id, **kwargs): + """Deletes the key identified by the specified id. + + A NotAuthorized exception is raised if the context is None and a + KeyError is raised if the UUID is invalid. + """ + if ctxt is None: + raise exception.NotAuthorized() + + del self.keys[key_id] diff --git a/nova/keymgr/single_key_mgr.py b/nova/keymgr/single_key_mgr.py new file mode 100644 index 0000000000..d41e843814 --- /dev/null +++ b/nova/keymgr/single_key_mgr.py @@ -0,0 +1,73 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2013 The Johns Hopkins University/Applied Physics Laboratory +# All Rights Reserved. +# +# 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. + +""" +An implementation of a key manager that returns a single key in response to +all invocations of get_key. +""" + + +from nova import exception +from nova.keymgr import mock_key_mgr +from nova.openstack.common.gettextutils import _ +from nova.openstack.common import log as logging + + +LOG = logging.getLogger(__name__) + + +class SingleKeyManager(mock_key_mgr.MockKeyManager): + """ + This key manager implementation supports all the methods specified by the + key manager interface. This implementation creates a single key in response + to all invocations of create_key. Side effects (e.g., raising exceptions) + for each method are handled as specified by the key manager interface. + """ + + def __init__(self): + LOG.warn(_('This key manager is insecure and is not recommended for ' + 'production deployments')) + super(SingleKeyManager, self).__init__() + + self.key_id = '00000000-0000-0000-0000-000000000000' + self.key = self._generate_key(key_length=256) + + # key should exist by default + self.keys[self.key_id] = self.key + + def _generate_hex_key(self, **kwargs): + key_length = kwargs.get('key_length', 256) + return '0' * (key_length / 4) # hex digit => 4 bits + + def _generate_key_id(self): + return self.key_id + + def store_key(self, ctxt, key, **kwargs): + if key != self.key: + raise exception.KeyManagerError( + reason="cannot store arbitrary keys") + + return super(SingleKeyManager, self).store_key(ctxt, key, **kwargs) + + def delete_key(self, ctxt, key_id, **kwargs): + if ctxt is None: + raise exception.NotAuthorized() + + if key_id != self.key_id: + raise exception.KeyManagerError( + reason="cannot delete non-existent key") + + LOG.warn(_("Not deleting key %s"), key_id) |