Codebase list python-castellan / d3446f5
Merge "Support handling legacy all-zeros key ID" Zuul authored 6 years ago Gerrit Code Review committed 6 years ago
4 changed file(s) with 211 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
1111 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1212 # License for the specific language governing permissions and limitations
1313 # under the License.
14 from castellan.key_manager import migration
1415 from oslo_config import cfg
1516 from oslo_log import log as logging
1617 from oslo_utils import importutils
4041 conf.key_manager.backend,
4142 invoke_on_load=True,
4243 invoke_args=[conf])
43 return mgr.driver
44 key_mgr = mgr.driver
4445 except exception.NoMatches:
4546 LOG.warning("Deprecation Warning : %s is not a stevedore based driver,"
4647 " trying to load it as a class", conf.key_manager.backend)
4748 cls = importutils.import_class(conf.key_manager.backend)
48 return cls(configuration=conf)
49 key_mgr = cls(configuration=conf)
50
51 return migration.handle_migration(conf, key_mgr)
0 # Copyright 2017 Red Hat, Inc.
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14 import binascii
15 from castellan.common import exception
16 from castellan.common.objects import symmetric_key
17 from oslo_config import cfg
18 from oslo_log import log as logging
19
20 LOG = logging.getLogger(__name__)
21
22
23 def handle_migration(conf, key_mgr):
24 try:
25 conf.register_opt(cfg.StrOpt('fixed_key'), group='key_manager')
26 except cfg.DuplicateOptError:
27 pass
28
29 if conf.key_manager.fixed_key is not None and \
30 not conf.key_manager.backend.endswith('ConfKeyManager'):
31
32 LOG.warning("Using MigrationKeyManager to provide support for legacy"
33 " fixed_key encryption")
34
35 class MigrationKeyManager(type(key_mgr)):
36 def __init__(self, configuration):
37 self.fixed_key = configuration.key_manager.fixed_key
38 self.fixed_key_id = '00000000-0000-0000-0000-000000000000'
39 super(MigrationKeyManager, self).__init__(configuration)
40
41 def get(self, context, managed_object_id):
42 if managed_object_id == self.fixed_key_id:
43 LOG.debug("Processing request for secret associated"
44 " with fixed_key key ID")
45
46 if context is None:
47 raise exception.Forbidden()
48
49 key_bytes = bytes(binascii.unhexlify(self.fixed_key))
50 secret = symmetric_key.SymmetricKey('AES',
51 len(key_bytes) * 8,
52 key_bytes)
53 else:
54 secret = super(MigrationKeyManager, self).get(
55 context, managed_object_id)
56 return secret
57
58 def delete(self, context, managed_object_id):
59 if managed_object_id == self.fixed_key_id:
60 LOG.debug("Not deleting key associated with"
61 " fixed_key key ID")
62
63 if context is None:
64 raise exception.Forbidden()
65 else:
66 super(MigrationKeyManager, self).delete(context,
67 managed_object_id)
68
69 key_mgr = MigrationKeyManager(configuration=conf)
70
71 return key_mgr
0 # Copyright 2017 Red Hat, Inc.
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """
16 Test cases for the migration key manager.
17 """
18
19 import binascii
20 import mock
21
22 from oslo_config import cfg
23
24 from castellan.common import exception
25 from castellan.common.objects import symmetric_key as key
26 from castellan import key_manager
27 from castellan.key_manager import not_implemented_key_manager
28 from castellan.tests.unit.key_manager import test_key_manager
29
30 CONF = cfg.CONF
31
32
33 class ConfKeyManager(not_implemented_key_manager.NotImplementedKeyManager):
34 pass
35
36
37 class MigrationKeyManagerTestCase(test_key_manager.KeyManagerTestCase):
38
39 def _create_key_manager(self):
40 self.fixed_key = '1' * 64
41 try:
42 self.conf.register_opt(cfg.StrOpt('fixed_key'),
43 group='key_manager')
44 except cfg.DuplicateOptError:
45 pass
46 self.conf.set_override('fixed_key',
47 self.fixed_key,
48 group='key_manager')
49 return key_manager.API(self.conf)
50
51 def setUp(self):
52 super(MigrationKeyManagerTestCase, self).setUp()
53
54 # Create fake context (actual contents doesn't matter).
55 self.ctxt = mock.Mock()
56
57 fixed_key_bytes = bytes(binascii.unhexlify(self.fixed_key))
58 fixed_key_length = len(fixed_key_bytes) * 8
59 self.fixed_key_secret = key.SymmetricKey('AES',
60 fixed_key_length,
61 fixed_key_bytes)
62 self.fixed_key_id = '00000000-0000-0000-0000-000000000000'
63 self.other_key_id = "d152fa13-2b41-42ca-a934-6c21566c0f40"
64
65 def test_get_fixed_key(self):
66 self.assertEqual('MigrationKeyManager', type(self.key_mgr).__name__)
67 secret = self.key_mgr.get(self.ctxt, self.fixed_key_id)
68 self.assertEqual(self.fixed_key_secret, secret)
69
70 def test_get_fixed_key_fail_bad_context(self):
71 self.assertRaises(exception.Forbidden,
72 self.key_mgr.get,
73 context=None,
74 managed_object_id=self.fixed_key_id)
75
76 def test_delete_fixed_key(self):
77 self.key_mgr.delete(self.ctxt, self.fixed_key_id)
78 # Delete looks like it succeeded, but nothing actually happened.
79 secret = self.key_mgr.get(self.ctxt, self.fixed_key_id)
80 self.assertEqual(self.fixed_key_secret, secret)
81
82 def test_delete_fixed_key_fail_bad_context(self):
83 self.assertRaises(exception.Forbidden,
84 self.key_mgr.delete,
85 context=None,
86 managed_object_id=self.fixed_key_id)
87
88 def test_get_other_key(self):
89 # Request to get other_key_id should be passed on to the backend,
90 # who will throw an error because we don't have a valid context.
91 self.assertRaises(exception.KeyManagerError,
92 self.key_mgr.get,
93 context=self.ctxt,
94 managed_object_id=self.other_key_id)
95
96 def test_delete_other_key(self):
97 # Request to delete other_key_id should be passed on to the backend,
98 # who will throw an error because we don't have a valid context.
99 self.assertRaises(exception.KeyManagerError,
100 self.key_mgr.delete,
101 context=self.ctxt,
102 managed_object_id=self.other_key_id)
103
104 def test_no_fixed_key(self):
105 conf = self.conf
106 conf.set_override('fixed_key', None, group='key_manager')
107 key_mgr = key_manager.API(conf)
108 self.assertNotEqual('MigrationKeyManager', type(key_mgr).__name__)
109 self.assertRaises(exception.KeyManagerError,
110 key_mgr.get,
111 context=self.ctxt,
112 managed_object_id=self.fixed_key_id)
113
114 def test_using_conf_key_manager(self):
115 conf = self.conf
116 ckm_backend = 'castellan.tests.unit.key_manager.' \
117 'test_migration_key_manager.ConfKeyManager'
118 conf.set_override('backend', ckm_backend, group='key_manager')
119 key_mgr = key_manager.API(conf)
120 self.assertNotEqual('MigrationKeyManager', type(key_mgr).__name__)
121 self.assertRaises(NotImplementedError,
122 key_mgr.get,
123 context=self.ctxt,
124 managed_object_id=self.fixed_key_id)
0 ---
1 features:
2 - |
3 Enhance the key manager to handle requests containing the special (all
4 zeros) managed object ID associated with Cinder's and Nova's legacy
5 ConfKeyManager. The purpose of this feature is to help users migrate from
6 the ConfKeyManager to a modern key manager such as Barbican. The feature
7 works by ensuring the ConfKeyManager's all-zeros key ID continues to
8 function when Barbican or Vault is the key manager.