Codebase list python-castellan / d1d8568
Add ability to get only metadata Adds the ability to retrieve only the metadata of a secret. This is helpful in situations when the caller wants to know information about the secret, but doesn't want to unnecessarily handle the secret data. Change-Id: I63aec037973aad2555190ca3eb6bba765955399a Kaitlin Farr 7 years ago
12 changed file(s) with 118 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
7676 specified.
7777 """
7878 pass
79
80 def is_metadata_only(self):
81 """Returns if the associated object is only metadata or not."""
82 return self.get_encoded() is None
453453 else:
454454 return secret.payload
455455
456 def _get_castellan_object(self, secret):
456 def _get_castellan_object(self, secret, metadata_only=False):
457457 """Creates a Castellan managed object given the Barbican secret.
458458
459 :param secret: the secret from barbican with the payload of data
459 The python barbicanclient lazy-loads the secret data, i.e. the secret
460 data is not requested until secret.payload is called. If the user
461 specifies metadata_only=True, secret.payload is never called,
462 preventing unnecessary loading of secret data.
463
464 :param secret: the barbican secret object
465 :metadata_only: boolean indicating if the secret bytes should be
466 included in the managed object
460467 :returns: the castellan object
461468 """
462469 secret_type = op_data.OpaqueData
464471 if barbican_type == secret.secret_type:
465472 secret_type = castellan_type
466473
467 secret_data = self._get_secret_data(secret)
474 if metadata_only:
475 secret_data = None
476 else:
477 secret_data = self._get_secret_data(secret)
468478
469479 # convert created ISO8601 in Barbican to POSIX
470480 if secret.created:
513523 else:
514524 return False
515525
516 def get(self, context, managed_object_id):
526 def get(self, context, managed_object_id, metadata_only=False):
517527 """Retrieves the specified managed object.
518528
519529 :param context: contains information of the user and the environment
520530 for the request (castellan/context.py)
521531 :param managed_object_id: the UUID of the object to retrieve
532 :param metadata_only: whether secret data should be included
522533 :return: ManagedObject representation of the managed object
523534 :raises KeyManagerError: if object retrieval fails
524535 :raises ManagedObjectNotFoundError: if object not found
525536 """
526537 try:
527538 secret = self._get_secret(context, managed_object_id)
528 return self._get_castellan_object(secret)
539 return self._get_castellan_object(secret, metadata_only)
529540 except (barbican_exceptions.HTTPAuthError,
530541 barbican_exceptions.HTTPClientError,
531542 barbican_exceptions.HTTPServerError) as e:
7373 pass
7474
7575 @abc.abstractmethod
76 def get(self, context, managed_object_id):
76 def get(self, context, managed_object_id, metadata_only=False):
7777 """Retrieves the specified managed object.
7878
7979 Implementations should verify that the caller has permissions to
8080 retrieve the managed object by checking the context object passed in
8181 as context. If the user lacks permission then a NotAuthorized
8282 exception is raised.
83
84 If the caller requests only metadata, then the object that is
85 returned will contain only the secret metadata and no secret bytes.
8386
8487 If the specified object does not exist, then a KeyError should be
8588 raised. Implementations should preclude users from discerning the
135135 retrieved_object = self.key_mgr.get(self.ctxt, uuid)
136136 self.assertEqual(managed_object.get_encoded(),
137137 retrieved_object.get_encoded())
138 self.assertFalse(managed_object.is_metadata_only())
139
140 @utils.parameterized_dataset({
141 'symmetric_key': [_get_test_symmetric_key()],
142 'public_key': [_get_test_public_key()],
143 'private_key': [_get_test_private_key()],
144 'certificate': [_get_test_certificate()],
145 'passphrase': [_get_test_passphrase()],
146 'opaque_data': [_get_test_opaque_data()],
147 })
148 def test_get_metadata(self, managed_object):
149 uuid = self._get_valid_object_uuid(managed_object)
150 self.addCleanup(self.key_mgr.delete, self.ctxt, uuid)
151
152 retrieved_object = self.key_mgr.get(self.ctxt,
153 uuid,
154 metadata_only=True)
155 self.assertFalse(managed_object.is_metadata_only())
156 self.assertTrue(retrieved_object.is_metadata_only())
138157
139158 @utils.parameterized_dataset({
140159 'symmetric_key': [_get_test_symmetric_key()],
165165
166166 return key_id
167167
168 def get(self, context, managed_object_id, **kwargs):
168 def get(self, context, managed_object_id, metadata_only=False, **kwargs):
169169 """Retrieves the key identified by the specified id.
170170
171171 This implementation returns the key that is associated with the
175175 if context is None:
176176 raise exception.Forbidden()
177177
178 return self.keys[managed_object_id]
178 obj = self.keys[managed_object_id]
179 if metadata_only:
180 if hasattr(obj, "_key"):
181 obj._key = None
182 if hasattr(obj, "_data"):
183 obj._data = None
184 if hasattr(obj, "_passphrase"):
185 obj._passphrase = None
186 return obj
179187
180188 def delete(self, context, managed_object_id, **kwargs):
181189 """Deletes the object identified by the specified id.
147147 actual_key = self.key_mgr.get(self.context, key_id)
148148 self.assertEqual(_key, actual_key)
149149
150 def test_store_key_and_get_metadata(self):
151 secret_key = bytes(b'0' * 64)
152 _key = sym_key.SymmetricKey('AES', 64 * 8, secret_key)
153 key_id = self.key_mgr.store(self.context, _key)
154
155 actual_key = self.key_mgr.get(self.context,
156 key_id,
157 metadata_only=True)
158 self.assertIsNone(actual_key.get_encoded())
159 self.assertTrue(actual_key.is_metadata_only())
160
150161 def test_store_null_context(self):
151162 self.assertRaises(exception.Forbidden,
152163 self.key_mgr.store, None, None)
3333 self.opaque_data = self._create_data()
3434
3535 super(OpaqueDataTestCase, self).setUp()
36
37 def test_is_not_only_metadata(self):
38 self.assertFalse(self.opaque_data.is_metadata_only())
39
40 def test_is_only_metadata(self):
41 d = opaque_data.OpaqueData(None, self.name, self.created)
42 self.assertTrue(d.is_metadata_only())
3643
3744 def test_get_format(self):
3845 self.assertEqual('Opaque', self.opaque_data.format)
3333 self.passphrase = self._create_passphrase()
3434
3535 super(PassphraseTestCase, self).setUp()
36
37 def test_is_not_only_metadata(self):
38 self.assertFalse(self.passphrase.is_metadata_only())
39
40 def test_is_only_metadata(self):
41 p = passphrase.Passphrase(None, self.name, self.created)
42 self.assertTrue(p.is_metadata_only())
3643
3744 def test_get_format(self):
3845 self.assertEqual('RAW', self.passphrase.format)
3737 self.created = 1448088699
3838
3939 super(PrivateKeyTestCase, self).setUp()
40
41 def test_is_not_only_metadata(self):
42 self.assertFalse(self.key.is_metadata_only())
43
44 def test_is_only_metadata(self):
45 k = private_key.PrivateKey(self.algorithm,
46 self.bit_length,
47 None,
48 self.name,
49 self.created)
50 self.assertTrue(k.is_metadata_only())
4051
4152 def test_get_algorithm(self):
4253 self.assertEqual(self.algorithm, self.key.algorithm)
3737 self.created = 1448088699
3838
3939 super(PublicKeyTestCase, self).setUp()
40
41 def test_is_not_only_metadata(self):
42 self.assertFalse(self.key.is_metadata_only())
43
44 def test_is_only_metadata(self):
45 k = public_key.PublicKey(self.algorithm,
46 self.bit_length,
47 None,
48 self.name,
49 self.created)
50 self.assertTrue(k.is_metadata_only())
4051
4152 def test_get_algorithm(self):
4253 self.assertEqual(self.algorithm, self.key.algorithm)
3636 self.created = 1448088699
3737
3838 super(SymmetricKeyTestCase, self).setUp()
39
40 def test_is_not_only_metadata(self):
41 self.assertFalse(self.key.is_metadata_only())
42
43 def test_is_only_metadata(self):
44 k = sym_key.SymmetricKey(self.algorithm,
45 self.bit_length,
46 None,
47 self.name,
48 self.created)
49 self.assertTrue(k.is_metadata_only())
3950
4051 def test_get_format(self):
4152 self.assertEqual('RAW', self.key.format)
3333 self.created = 1448088699
3434
3535 super(X509TestCase, self).setUp()
36
37 def test_is_not_only_metadata(self):
38 self.assertFalse(self.cert.is_metadata_only())
39
40 def test_is_only_metadata(self):
41 c = x_509.X509(None, self.name, self.created)
42 self.assertTrue(c.is_metadata_only())
3643
3744 def test_get_format(self):
3845 self.assertEqual('X.509', self.cert.format)