Codebase list python-castellan / c347f4d
Merge "Add name to Castellan Objects and Barbican Key Manager" Jenkins authored 8 years ago Gerrit Code Review committed 8 years ago
16 changed file(s) with 164 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
2828 class ManagedObject(object):
2929 """Base class to represent all managed objects."""
3030
31 def __init__(self, name=None):
32 """Managed Object has a name, defaulted to None."""
33 self._name = name
34
35 @property
36 def name(self):
37 """Returns the name.
38
39 Returns the object's name or None if this object does not have one.
40 """
41 return self._name
42
3143 @abc.abstractproperty
3244 def format(self):
3345 """Returns the encoding format.
2424 class OpaqueData(managed_object.ManagedObject):
2525 """This class represents opaque data."""
2626
27 def __init__(self, data):
27 def __init__(self, data, name=None):
2828 """Create a new OpaqueData object.
2929
3030 Expected type for data is a bytestring.
3131 """
3232 self._data = data
33 super(OpaqueData, self).__init__(name=name)
3334
3435 @property
3536 def format(self):
4243
4344 def __eq__(self, other):
4445 if isinstance(other, OpaqueData):
45 return self._data == other._data
46 return (self._data == other._data and
47 self._name == other._name)
4648 else:
4749 return False
4850
2424 class Passphrase(managed_object.ManagedObject):
2525 """This class represents a passphrase."""
2626
27 def __init__(self, passphrase):
27 def __init__(self, passphrase, name=None):
2828 """Create a new Passphrase object.
2929
3030 The expected type for the passphrase is a bytestring.
3131 """
3232 self._passphrase = passphrase
33 super(Passphrase, self).__init__(name=name)
3334
3435 @property
3536 def format(self):
4243
4344 def __eq__(self, other):
4445 if isinstance(other, Passphrase):
45 return self._passphrase == other._passphrase
46 return (self._passphrase == other._passphrase and
47 self._name == other._name)
4648 else:
4749 return False
4850
2424 class PrivateKey(key.Key):
2525 """This class represents private keys."""
2626
27 def __init__(self, algorithm, bit_length, key):
27 def __init__(self, algorithm, bit_length, key, name=None):
2828 """Create a new PrivateKey object.
2929
3030 The arguments specify the algorithm and bit length for the asymmetric
3333 self._alg = algorithm
3434 self._bit_length = bit_length
3535 self._key = key
36 super(PrivateKey, self).__init__(name=name)
3637
3738 @property
3839 def algorithm(self):
5657 def __eq__(self, other):
5758 if isinstance(other, PrivateKey):
5859 return (self._alg == other._alg and
59 self._key == other._key)
60 self._key == other._key and
61 self._name == other._name)
6062 else:
6163 return False
6264
2424 class PublicKey(key.Key):
2525 """This class represents public keys."""
2626
27 def __init__(self, algorithm, bit_length, key):
27 def __init__(self, algorithm, bit_length, key, name=None):
2828 """Create a new PublicKey object.
2929
3030 The arguments specify the algorithm and bit length for the asymmetric
3434 self._alg = algorithm
3535 self._bit_length = bit_length
3636 self._key = key
37 super(PublicKey, self).__init__(name=name)
3738
3839 @property
3940 def algorithm(self):
5758 def __eq__(self, other):
5859 if isinstance(other, PublicKey):
5960 return (self._alg == other._alg and
60 self._key == other._key)
61 self._key == other._key and
62 self._name == other._name)
6163 else:
6264 return False
6365
2424 class SymmetricKey(key.Key):
2525 """This class represents symmetric keys."""
2626
27 def __init__(self, algorithm, bit_length, key):
27 def __init__(self, algorithm, bit_length, key, name=None):
2828 """Create a new SymmetricKey object.
2929
3030 The arguments specify the algorithm and bit length for the symmetric
3333 self._alg = algorithm
3434 self._bit_length = bit_length
3535 self._key = key
36 super(SymmetricKey, self).__init__(name=name)
3637
3738 @property
3839 def algorithm(self):
5758 if isinstance(other, SymmetricKey):
5859 return (self._alg == other._alg and
5960 self._bit_length == other._bit_length and
60 self._key == other._key)
61 self._key == other._key and
62 self._name == other._name)
6163 else:
6264 return False
6365
2424 class X509(certificate.Certificate):
2525 """This class represents X.509 certificates."""
2626
27 def __init__(self, data):
27 def __init__(self, data, name=None):
2828 """Create a new X509 object.
2929
3030 The data should be in a bytestring.
3131 """
3232 self._data = data
33 super(X509, self).__init__(name=name)
3334
3435 @property
3536 def format(self):
4243
4344 def __eq__(self, other):
4445 if isinstance(other, X509):
45 return (self._data == other._data)
46 return (self._data == other._data and
47 self._name == other._name)
4648 else:
4749 return False
4850
165165 endpoint, api_version)
166166 return base_url
167167
168 def create_key(self, context, algorithm, length, expiration=None):
168 def create_key(self, context, algorithm, length,
169 expiration=None, name=None):
169170 """Creates a symmetric key.
170171
171172 :param context: contains information of the user and the environment
172173 for the request (castellan/context.py)
173174 :param algorithm: the algorithm associated with the secret
174175 :param length: the bit length of the secret
176 :param name: the name of the key
175177 :param expiration: the date the key will expire
176178 :return: the UUID of the new key
177179 :raises KeyManagerError: if key creation fails
180182
181183 try:
182184 key_order = barbican_client.orders.create_key(
185 name=name,
183186 algorithm=algorithm,
184187 bit_length=length,
185188 expiration=expiration)
192195 LOG.error(u._LE("Error creating key: %s"), e)
193196 raise exception.KeyManagerError(reason=e)
194197
195 def create_key_pair(self, context, algorithm, length, expiration=None):
198 def create_key_pair(self, context, algorithm, length,
199 expiration=None, name=None):
196200 """Creates an asymmetric key pair.
197201
198202 :param context: contains information of the user and the environment
199203 for the request (castellan/context.py)
200204 :param algorithm: the algorithm associated with the secret
201205 :param length: the bit length of the secret
206 :param name: the name of the key
202207 :param expiration: the date the key will expire
203208 :return: the UUIDs of the new key, in the order (private, public)
204209 :raises NotImplementedError: until implemented
210215 key_pair_order = barbican_client.orders.create_asymmetric(
211216 algorithm=algorithm,
212217 bit_length=length,
218 name=name,
213219 expiration=expiration)
214220
215221 order_ref = key_pair_order.submit()
229235
230236 def _get_barbican_object(self, barbican_client, managed_object):
231237 """Converts the Castellan managed_object to a Barbican secret."""
238 name = getattr(managed_object, 'name', None)
239
232240 try:
233241 algorithm = managed_object.algorithm
234242 bit_length = managed_object.bit_length
243251 secret = barbican_client.secrets.create(payload=payload,
244252 algorithm=algorithm,
245253 bit_length=bit_length,
254 name=name,
246255 secret_type=secret_type)
247256 return secret
248257
282291
283292 :param context: contains information of the user and the environment
284293 for the request (castellan/context.py)
285 :param managed_object: the unencrypted secret data. Known as "payload"
286 to the barbicanclient api
294 :param managed_object: a secret object with unencrypted payload.
295 Known as "secret" to the barbicanclient api
287296 :param expiration: the expiration time of the secret in ISO 8601
288297 format
289298 :returns: the UUID of the stored object
414423 if issubclass(secret_type, key_base_class.Key):
415424 return secret_type(secret.algorithm,
416425 secret.bit_length,
417 secret_data)
426 secret_data,
427 secret.name)
418428 else:
419 return secret_type(secret_data)
429 return secret_type(secret_data,
430 secret.name)
420431
421432 def _get_secret(self, context, object_id):
422433 """Returns the metadata of the secret.
3939 pass
4040
4141 @abc.abstractmethod
42 def create_key(self, context, algorithm, length, expiration=None):
42 def create_key(self, context, algorithm, length,
43 expiration=None, name=None):
4344 """Creates a symmetric key.
4445
4546 This method creates a symmetric key and returns the key's UUID. If the
4950 pass
5051
5152 @abc.abstractmethod
52 def create_key_pair(self, context, algorithm, length, expiration=None):
53 def create_key_pair(self, context, algorithm, length,
54 expiration=None, name=None):
5355 """Creates an asymmetric key pair.
5456
5557 This method creates an asymmetric key pair and returns the pair of key
185185 original_secret_metadata.algorithm = mock.sentinel.alg
186186 original_secret_metadata.bit_length = mock.sentinel.bit
187187 original_secret_metadata.secret_type = 'symmetric'
188
189 key_name = 'my key'
190 original_secret_metadata.name = key_name
191
188192 original_secret_data = b'test key'
189193 original_secret_metadata.payload = original_secret_data
190194
192196 key = self.key_mgr.get(self.ctxt, self.key_id)
193197
194198 self.get.assert_called_once_with(self.secret_ref)
199 self.assertEqual(key_name, key.name)
195200 self.assertEqual(original_secret_data, key.get_encoded())
196201
197202 def test_get_null_context(self):
227232
228233 self.create.assert_called_once_with(algorithm='AES',
229234 bit_length=key_length,
235 name=None,
230236 payload=secret_key,
237 secret_type='symmetric')
238 self.assertEqual(self.key_id, returned_uuid)
239
240 def test_store_key_with_name(self):
241 # Create Key to store
242 secret_key = bytes(b'\x01\x02\xA0\xB3')
243 key_length = len(secret_key) * 8
244 secret_name = 'My Secret'
245 _key = sym_key.SymmetricKey('AES',
246 key_length,
247 secret_key,
248 secret_name)
249
250 # Define the return values
251 secret = mock.Mock()
252 self.create.return_value = secret
253 secret.store.return_value = self.secret_ref
254
255 # Store the Key
256 returned_uuid = self.key_mgr.store(self.ctxt, _key)
257
258 self.create.assert_called_once_with(algorithm='AES',
259 bit_length=key_length,
260 payload=secret_key,
261 name=secret_name,
231262 secret_type='symmetric')
232263 self.assertEqual(self.key_id, returned_uuid)
233264
2323 class OpaqueDataTestCase(base.TestCase):
2424
2525 def _create_data(self):
26 return opaque_data.OpaqueData(self.data)
26 return opaque_data.OpaqueData(self.data, self.name)
2727
2828 def setUp(self):
2929 self.data = bytes(b"secret opaque data")
30 self.name = 'my opaque'
3031 self.opaque_data = self._create_data()
3132
3233 super(OpaqueDataTestCase, self).setUp()
3738 def test_get_encoded(self):
3839 self.assertEqual(self.data, self.opaque_data.get_encoded())
3940
41 def test_get_name(self):
42 self.assertEqual(self.name, self.opaque_data.name)
43
4044 def test___eq__(self):
4145 self.assertTrue(self.opaque_data == self.opaque_data)
4246
4549
4650 def test___ne__(self):
4751 self.assertFalse(self.opaque_data != self.opaque_data)
52 self.assertFalse(self.name != self.name)
4853
4954 self.assertTrue(self.opaque_data is not None)
5055 self.assertTrue(None != self.opaque_data)
56
57 def test___ne__name(self):
58 other_opaque = opaque_data.OpaqueData(self.data, "other opaque")
59 self.assertTrue(self.opaque_data != other_opaque)
2323 class PassphraseTestCase(base.TestCase):
2424
2525 def _create_passphrase(self):
26 return passphrase.Passphrase(self.passphrase_data)
26 return passphrase.Passphrase(self.passphrase_data,
27 self.name)
2728
2829 def setUp(self):
2930 self.passphrase_data = bytes(b"secret passphrase")
31 self.name = 'my phrase'
3032 self.passphrase = self._create_passphrase()
3133
3234 super(PassphraseTestCase, self).setUp()
3739 def test_get_encoded(self):
3840 self.assertEqual(self.passphrase_data, self.passphrase.get_encoded())
3941
42 def test_get_name(self):
43 self.assertEqual(self.name, self.passphrase.name)
44
4045 def test___eq__(self):
4146 self.assertTrue(self.passphrase == self.passphrase)
4247
4550
4651 def test___ne__(self):
4752 self.assertFalse(self.passphrase != self.passphrase)
53 self.assertFalse(self.name != self.name)
4854
4955 self.assertTrue(self.passphrase is not None)
5056 self.assertTrue(None != self.passphrase)
57
58 def test___ne__name(self):
59 other_phrase = passphrase.Passphrase(self.passphrase_data,
60 "other phrase")
61 self.assertTrue(self.passphrase_data != other_phrase)
2626 def _create_key(self):
2727 return private_key.PrivateKey(self.algorithm,
2828 self.length,
29 self.encoded)
29 self.encoded,
30 self.name)
3031
3132 def setUp(self):
3233 self.algorithm = 'RSA'
3334 self.length = 2048
3435 self.encoded = bytes(utils.get_private_key_der())
36 self.name = 'my key'
3537
3638 super(PrivateKeyTestCase, self).setUp()
3739
4042
4143 def test_get_length(self):
4244 self.assertEqual(self.length, self.key.bit_length)
45
46 def test_get_name(self):
47 self.assertEqual(self.name, self.key.name)
4348
4449 def test_get_format(self):
4550 self.assertEqual('PKCS8', self.key.format)
5560
5661 def test___ne__(self):
5762 self.assertFalse(self.key != self.key)
63 self.assertFalse(self.name != self.name)
5864
5965 self.assertTrue(self.key is not None)
6066 self.assertTrue(None != self.key)
67
68 def test___ne__name(self):
69 other_key = private_key.PrivateKey(self.algorithm,
70 self.length,
71 self.encoded,
72 'other key')
73 self.assertTrue(self.key != other_key)
2424 class PublicKeyTestCase(base.KeyTestCase):
2525
2626 def _create_key(self):
27 return public_key.PublicKey(self.algorithm, self.length, self.encoded)
27 return public_key.PublicKey(self.algorithm,
28 self.length,
29 self.encoded,
30 self.name)
2831
2932 def setUp(self):
3033 self.algorithm = 'RSA'
3134 self.length = 2048
3235 self.encoded = bytes(utils.get_public_key_der())
36 self.name = 'my key'
3337
3438 super(PublicKeyTestCase, self).setUp()
3539
3842
3943 def test_get_length(self):
4044 self.assertEqual(self.length, self.key.bit_length)
45
46 def test_get_name(self):
47 self.assertEqual(self.name, self.key.name)
4148
4249 def test_get_format(self):
4350 self.assertEqual('SubjectPublicKeyInfo', self.key.format)
5360
5461 def test___ne__(self):
5562 self.assertFalse(self.key != self.key)
63 self.assertFalse(self.name != self.name)
5664
5765 self.assertTrue(self.key is not None)
5866 self.assertTrue(None != self.key)
67
68 def test___ne__name(self):
69 other_key = public_key.PublicKey(self.algorithm,
70 self.length,
71 self.encoded,
72 'other key')
73 self.assertTrue(self.key != other_key)
2525 def _create_key(self):
2626 return sym_key.SymmetricKey(self.algorithm,
2727 self.bit_length,
28 self.encoded)
28 self.encoded,
29 self.name)
2930
3031 def setUp(self):
3132 self.algorithm = 'AES'
3233 self.encoded = bytes(b'0' * 64)
3334 self.bit_length = len(self.encoded) * 8
35 self.name = 'my key'
3436
3537 super(SymmetricKeyTestCase, self).setUp()
3638
3739 def test_get_format(self):
3840 self.assertEqual('RAW', self.key.format)
41
42 def test_get_name(self):
43 self.assertEqual(self.name, self.key.name)
3944
4045 def test_get_encoded(self):
4146 self.assertEqual(self.encoded, self.key.get_encoded())
5459
5560 def test___ne__(self):
5661 self.assertFalse(self.key != self.key)
62 self.assertFalse(self.name != self.name)
5763
5864 self.assertTrue(self.key is not None)
5965 self.assertTrue(None != self.key)
66
67 def test___ne__name(self):
68 other_key = sym_key.SymmetricKey(self.algorithm,
69 self.bit_length,
70 self.encoded,
71 'other key')
72 self.assertTrue(self.key != other_key)
2424 class X509TestCase(base.CertificateTestCase):
2525
2626 def _create_cert(self):
27 return x_509.X509(self.data)
27 return x_509.X509(self.data, self.name)
2828
2929 def setUp(self):
3030 self.data = utils.get_certificate_der()
31 self.name = 'my cert'
3132
3233 super(X509TestCase, self).setUp()
3334
3435 def test_get_format(self):
3536 self.assertEqual('X.509', self.cert.format)
37
38 def test_get_name(self):
39 self.assertEqual(self.name, self.cert.name)
3640
3741 def test_get_encoded(self):
3842 self.assertEqual(self.data, self.cert.get_encoded())
4549
4650 def test___ne__(self):
4751 self.assertFalse(self.cert != self.cert)
52 self.assertFalse(self.name != self.name)
4853
4954 self.assertTrue(self.cert is not None)
5055 self.assertTrue(None != self.cert)
56
57 def test___ne__name(self):
58 other_x509 = x_509.X509(self.data, "other x509")
59 self.assertTrue(self.cert != other_x509)