summaryrefslogtreecommitdiff
path: root/nova/keymgr
diff options
context:
space:
mode:
authorDan Prince <dprince@redhat.com>2013-09-12 11:14:30 -0400
committerDan Prince <dprince@redhat.com>2013-09-13 07:08:16 -0400
commita0d785868c859fcd016bbcfb033340e187721054 (patch)
tree3d757638bb05363e7818eb2f8a64df46fdfb2997 /nova/keymgr
parent2f6022f6bff9172a075b01c6cb6f87a4b4aabeb8 (diff)
downloadnova-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.py2
-rw-r--r--nova/keymgr/mock_key_mgr.py139
-rw-r--r--nova/keymgr/single_key_mgr.py73
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)