Add ID to managed objects
The managed objects did not have an ID associated with them. This is most
helpful for the list command, where once you have more than one object,
it's hard to track unique identifiers for the objects.
Change-Id: Ibc48762e7c2c71659fb96826c53301bc6f55ddf7
Kaitlin Farr
6 years ago
27 | 27 | class ManagedObject(object): |
28 | 28 | """Base class to represent all managed objects.""" |
29 | 29 | |
30 | def __init__(self, name=None, created=None): | |
30 | def __init__(self, name=None, created=None, id=None): | |
31 | 31 | """Managed Object |
32 | 32 | |
33 | 33 | :param name: the name of the managed object. |
34 | 34 | :param created: the time a managed object was created. |
35 | :param id: the ID of the object, generated after storing the object. | |
35 | 36 | """ |
36 | 37 | self._name = name |
37 | 38 | |
41 | 42 | else: |
42 | 43 | raise ValueError('created must be of long type, actual type %s' % |
43 | 44 | type(created)) |
45 | ||
46 | self._id = id | |
47 | ||
48 | @property | |
49 | def id(self): | |
50 | """Returns the ID of the managed object. | |
51 | ||
52 | Returns the ID of the managed object or None if this object does not | |
53 | have one. If the ID is None, the object has not been persisted yet. | |
54 | """ | |
55 | return self._id | |
44 | 56 | |
45 | 57 | @property |
46 | 58 | def name(self): |
24 | 24 | class OpaqueData(managed_object.ManagedObject): |
25 | 25 | """This class represents opaque data.""" |
26 | 26 | |
27 | def __init__(self, data, name=None, created=None): | |
27 | def __init__(self, data, name=None, created=None, id=None): | |
28 | 28 | """Create a new OpaqueData object. |
29 | 29 | |
30 | 30 | Expected type for data is a bytestring. |
31 | 31 | """ |
32 | 32 | self._data = data |
33 | super(OpaqueData, self).__init__(name=name, created=created) | |
33 | super(OpaqueData, self).__init__(name=name, created=created, id=id) | |
34 | 34 | |
35 | 35 | @property |
36 | 36 | def format(self): |
24 | 24 | class Passphrase(managed_object.ManagedObject): |
25 | 25 | """This class represents a passphrase.""" |
26 | 26 | |
27 | def __init__(self, passphrase, name=None, created=None): | |
27 | def __init__(self, passphrase, name=None, created=None, id=None): | |
28 | 28 | """Create a new Passphrase object. |
29 | 29 | |
30 | 30 | The expected type for the passphrase is a bytestring. |
31 | 31 | """ |
32 | 32 | self._passphrase = passphrase |
33 | super(Passphrase, self).__init__(name=name, created=created) | |
33 | super(Passphrase, self).__init__(name=name, created=created, id=id) | |
34 | 34 | |
35 | 35 | @property |
36 | 36 | def format(self): |
25 | 25 | """This class represents private keys.""" |
26 | 26 | |
27 | 27 | def __init__(self, algorithm, bit_length, key, |
28 | name=None, created=None): | |
28 | name=None, created=None, id=None): | |
29 | 29 | """Create a new PrivateKey object. |
30 | 30 | |
31 | 31 | The arguments specify the algorithm and bit length for the asymmetric |
34 | 34 | self._alg = algorithm |
35 | 35 | self._bit_length = bit_length |
36 | 36 | self._key = key |
37 | super(PrivateKey, self).__init__(name=name, created=created) | |
37 | super(PrivateKey, self).__init__(name=name, created=created, id=id) | |
38 | 38 | |
39 | 39 | @property |
40 | 40 | def algorithm(self): |
25 | 25 | """This class represents public keys.""" |
26 | 26 | |
27 | 27 | def __init__(self, algorithm, bit_length, key, |
28 | name=None, created=None): | |
28 | name=None, created=None, id=None): | |
29 | 29 | """Create a new PublicKey object. |
30 | 30 | |
31 | 31 | The arguments specify the algorithm and bit length for the asymmetric |
35 | 35 | self._alg = algorithm |
36 | 36 | self._bit_length = bit_length |
37 | 37 | self._key = key |
38 | super(PublicKey, self).__init__(name=name, created=created) | |
38 | super(PublicKey, self).__init__(name=name, created=created, id=id) | |
39 | 39 | |
40 | 40 | @property |
41 | 41 | def algorithm(self): |
25 | 25 | """This class represents symmetric keys.""" |
26 | 26 | |
27 | 27 | def __init__(self, algorithm, bit_length, key, |
28 | name=None, created=None): | |
28 | name=None, created=None, id=None): | |
29 | 29 | """Create a new SymmetricKey object. |
30 | 30 | |
31 | 31 | The arguments specify the algorithm and bit length for the symmetric |
34 | 34 | self._alg = algorithm |
35 | 35 | self._bit_length = bit_length |
36 | 36 | self._key = key |
37 | super(SymmetricKey, self).__init__(name=name, created=created) | |
37 | super(SymmetricKey, self).__init__(name=name, created=created, id=id) | |
38 | 38 | |
39 | 39 | @property |
40 | 40 | def algorithm(self): |
24 | 24 | class X509(certificate.Certificate): |
25 | 25 | """This class represents X.509 certificates.""" |
26 | 26 | |
27 | def __init__(self, data, name=None, created=None): | |
27 | def __init__(self, data, name=None, created=None, id=None): | |
28 | 28 | """Create a new X509 object. |
29 | 29 | |
30 | 30 | The data should be in a bytestring. |
31 | 31 | """ |
32 | 32 | self._data = data |
33 | super(X509, self).__init__(name=name, created=created) | |
33 | super(X509, self).__init__(name=name, created=created, id=id) | |
34 | 34 | |
35 | 35 | @property |
36 | 36 | def format(self): |
479 | 479 | else: |
480 | 480 | secret_data = self._get_secret_data(secret) |
481 | 481 | |
482 | if secret.secret_ref: | |
483 | object_id = self._retrieve_secret_uuid(secret.secret_ref) | |
484 | else: | |
485 | object_id = None | |
486 | ||
482 | 487 | # convert created ISO8601 in Barbican to POSIX |
483 | 488 | if secret.created: |
484 | 489 | time_stamp = timeutils.parse_isotime( |
490 | 495 | secret.bit_length, |
491 | 496 | secret_data, |
492 | 497 | secret.name, |
493 | created) | |
498 | created, | |
499 | object_id) | |
494 | 500 | else: |
495 | 501 | return secret_type(secret_data, |
496 | 502 | secret.name, |
497 | created) | |
503 | created, | |
504 | object_id) | |
498 | 505 | |
499 | 506 | def _get_secret(self, context, object_id): |
500 | 507 | """Returns the metadata of the secret. |
136 | 136 | self.assertEqual(managed_object.get_encoded(), |
137 | 137 | retrieved_object.get_encoded()) |
138 | 138 | self.assertFalse(managed_object.is_metadata_only()) |
139 | self.assertFalse(retrieved_object.is_metadata_only()) | |
140 | self.assertIsNotNone(retrieved_object.id) | |
139 | 141 | |
140 | 142 | @utils.parameterized_dataset({ |
141 | 143 | 'symmetric_key': [_get_test_symmetric_key()], |
154 | 156 | metadata_only=True) |
155 | 157 | self.assertFalse(managed_object.is_metadata_only()) |
156 | 158 | self.assertTrue(retrieved_object.is_metadata_only()) |
159 | self.assertIsNotNone(retrieved_object.id) | |
157 | 160 | |
158 | 161 | @utils.parameterized_dataset({ |
159 | 162 | 'symmetric_key': [_get_test_symmetric_key()], |
170 | 173 | retrieved_object = self.key_mgr.get(self.ctxt, uuid) |
171 | 174 | self.assertEqual(managed_object.get_encoded(), |
172 | 175 | retrieved_object.get_encoded()) |
176 | self.assertIsNotNone(retrieved_object.id) | |
173 | 177 | |
174 | 178 | @utils.parameterized_dataset({ |
175 | 179 | 'symmetric_key': [_get_test_symmetric_key()], |
188 | 192 | # check if the object we created is in the list |
189 | 193 | retrieved_objects = self.key_mgr.list(self.ctxt) |
190 | 194 | self.assertTrue(managed_object in retrieved_objects) |
191 | for obj in retrieved_objects: | |
192 | self.assertFalse(obj.is_metadata_only()) | |
195 | for retrieved_object in retrieved_objects: | |
196 | self.assertFalse(retrieved_object.is_metadata_only()) | |
197 | self.assertIsNotNone(retrieved_object.id) | |
193 | 198 | |
194 | 199 | @utils.parameterized_dataset({ |
195 | 200 | 'symmetric_key': [_get_test_symmetric_key()], |
210 | 215 | # check if the object we created is in the list |
211 | 216 | retrieved_objects = self.key_mgr.list(self.ctxt, metadata_only=True) |
212 | 217 | self.assertTrue(expected_obj in retrieved_objects) |
213 | for obj in retrieved_objects: | |
214 | self.assertTrue(obj.is_metadata_only()) | |
218 | for retrieved_object in retrieved_objects: | |
219 | self.assertTrue(retrieved_object.is_metadata_only()) | |
220 | self.assertIsNotNone(retrieved_object.id) | |
215 | 221 | |
216 | 222 | @utils.parameterized_dataset({ |
217 | 223 | 'query_by_object_type': { |
232 | 238 | retrieved_objects = self.key_mgr.list(self.ctxt, **query_dict) |
233 | 239 | for retrieved_object in retrieved_objects: |
234 | 240 | self.assertEqual(type(object_1), type(retrieved_object)) |
241 | self.assertIsNotNone(retrieved_object.id) | |
235 | 242 | self.assertTrue(object_1 in retrieved_objects) |
162 | 162 | raise exception.Forbidden() |
163 | 163 | |
164 | 164 | key_id = self._generate_key_id() |
165 | managed_object._id = key_id | |
165 | 166 | self.keys[key_id] = managed_object |
166 | 167 | |
167 | 168 | return key_id |
188 | 188 | original_secret_metadata.bit_length = mock.sentinel.bit |
189 | 189 | original_secret_metadata.secret_type = 'symmetric' |
190 | 190 | |
191 | key_id = "43ed09c3-e551-4c24-b612-e619abe9b534" | |
192 | key_ref = ("http://localhost:9311/v1/secrets/" + key_id) | |
193 | original_secret_metadata.secret_ref = key_ref | |
194 | ||
191 | 195 | created = timeutils.parse_isotime('2015-10-20 18:51:17+00:00') |
192 | 196 | original_secret_metadata.created = created |
193 | 197 | created_formatted = timeutils.parse_isotime(str(created)) |
203 | 207 | key = self.key_mgr.get(self.ctxt, self.key_id) |
204 | 208 | |
205 | 209 | self.get.assert_called_once_with(self.secret_ref) |
210 | self.assertEqual(key_id, key.id) | |
206 | 211 | self.assertEqual(key_name, key.name) |
207 | 212 | self.assertEqual(original_secret_data, key.get_encoded()) |
208 | 213 | self.assertEqual(created_posix, key.created) |
359 | 364 | original_secret_metadata.bit_length = mock.sentinel.bit |
360 | 365 | original_secret_metadata.secret_type = 'symmetric' |
361 | 366 | |
367 | key_id = "43ed09c3-e551-4c24-b612-e619abe9b534" | |
368 | key_ref = ("http://localhost:9311/v1/secrets/" + key_id) | |
369 | original_secret_metadata.secret_ref = key_ref | |
370 | ||
362 | 371 | created = timeutils.parse_isotime('2015-10-20 18:51:17+00:00') |
363 | 372 | original_secret_metadata.created = created |
364 | 373 | created_formatted = timeutils.parse_isotime(str(created)) |
379 | 388 | key = key_list[0] |
380 | 389 | |
381 | 390 | self.list.assert_called_once() |
391 | self.assertEqual(key_id, key.id) | |
382 | 392 | self.assertEqual(key_name, key.name) |
383 | 393 | self.assertEqual(original_secret_data, key.get_encoded()) |
384 | 394 | self.assertEqual(created_posix, key.created) |
69 | 69 | key_id = self.key_mgr.create_key(self.context, length=length) |
70 | 70 | key = self.key_mgr.get(self.context, key_id) |
71 | 71 | self.assertEqual(length / 8, len(key.get_encoded())) |
72 | self.assertIsNotNone(key.id) | |
72 | 73 | |
73 | 74 | def test_create_key_with_name(self): |
74 | 75 | name = 'my key' |
75 | 76 | key_id = self.key_mgr.create_key(self.context, name=name) |
76 | 77 | key = self.key_mgr.get(self.context, key_id) |
77 | 78 | self.assertEqual(name, key.name) |
79 | self.assertIsNotNone(key.id) | |
78 | 80 | |
79 | 81 | def test_create_key_with_algorithm(self): |
80 | 82 | algorithm = 'DES' |
81 | 83 | key_id = self.key_mgr.create_key(self.context, algorithm=algorithm) |
82 | 84 | key = self.key_mgr.get(self.context, key_id) |
83 | 85 | self.assertEqual(algorithm, key.algorithm) |
86 | self.assertIsNotNone(key.id) | |
84 | 87 | |
85 | 88 | def test_create_key_null_context(self): |
86 | 89 | self.assertRaises(exception.Forbidden, |
93 | 96 | self.context, 'RSA', length, name=name) |
94 | 97 | |
95 | 98 | private_key = self.key_mgr.get(self.context, private_key_uuid) |
99 | self.assertIsNotNone(private_key.id) | |
96 | 100 | public_key = self.key_mgr.get(self.context, public_key_uuid) |
101 | self.assertIsNotNone(public_key.id) | |
97 | 102 | |
98 | 103 | crypto_private_key = get_cryptography_private_key(private_key) |
99 | 104 | crypto_public_key = get_cryptography_public_key(public_key) |
152 | 157 | actual_key = self.key_mgr.get(self.context, key_id) |
153 | 158 | self.assertEqual(_key, actual_key) |
154 | 159 | |
160 | self.assertIsNotNone(actual_key.id) | |
161 | ||
155 | 162 | def test_store_key_and_get_metadata(self): |
156 | 163 | secret_key = bytes(b'0' * 64) |
157 | 164 | _key = sym_key.SymmetricKey('AES', 64 * 8, secret_key) |
163 | 170 | self.assertIsNone(actual_key.get_encoded()) |
164 | 171 | self.assertTrue(actual_key.is_metadata_only()) |
165 | 172 | |
173 | self.assertIsNotNone(actual_key.id) | |
174 | ||
166 | 175 | def test_store_key_and_get_metadata_and_get_key(self): |
167 | 176 | secret_key = bytes(b'0' * 64) |
168 | 177 | _key = sym_key.SymmetricKey('AES', 64 * 8, secret_key) |
180 | 189 | self.assertIsNotNone(actual_key.get_encoded()) |
181 | 190 | self.assertFalse(actual_key.is_metadata_only()) |
182 | 191 | |
192 | self.assertIsNotNone(actual_key.id) | |
193 | ||
183 | 194 | def test_store_null_context(self): |
184 | 195 | self.assertRaises(exception.Forbidden, |
185 | 196 | self.key_mgr.store, None, None) |
219 | 230 | self.assertEqual(2, len(keys)) |
220 | 231 | self.assertTrue(key1 in keys) |
221 | 232 | self.assertTrue(key2 in keys) |
233 | ||
234 | for key in keys: | |
235 | self.assertIsNotNone(key.id) | |
222 | 236 | |
223 | 237 | def test_list_keys_metadata_only(self): |
224 | 238 | key1 = sym_key.SymmetricKey('AES', 64 * 8, bytes(b'0' * 64)) |
232 | 246 | for key in keys: |
233 | 247 | self.assertTrue(key.is_metadata_only()) |
234 | 248 | self.assertTrue(key.bit_length in bit_length_list) |
249 | ||
250 | for key in keys: | |
251 | self.assertIsNotNone(key.id) |