Add created property to Managed Objects

Adds the property 'created' to managed objects in Castellan.
The property is None until the secret has been stored.

Change-Id: I83e79cd3dbc07b90f4526a36aaf4ee76e902e228
This commit is contained in:
“Fernando 2015-10-21 11:01:35 -05:00 committed by Fernando Diaz
parent 0c877d424e
commit 31d467a35e
15 changed files with 179 additions and 102 deletions

View File

@ -19,7 +19,6 @@ Base ManagedObject Class
This module defines the ManagedObject class. The ManagedObject class
is the base class to represent all objects managed by the key manager.
"""
import abc
import six
@ -29,10 +28,21 @@ import six
class ManagedObject(object):
"""Base class to represent all managed objects."""
def __init__(self, name=None):
"""Managed Object has a name, defaulted to None."""
def __init__(self, name=None, created=None):
"""Managed Object
:param name: the name of the managed object.
:param created: the time a managed object was created.
"""
self._name = name
# If None or POSIX times
if not created or type(created) == int:
self._created = created
else:
raise ValueError('created must be of long type, actual type %s' %
type(created))
@property
def name(self):
"""Returns the name.
@ -41,6 +51,15 @@ class ManagedObject(object):
"""
return self._name
@property
def created(self):
"""Returns the POSIX time(long) of the object that was created.
Returns the POSIX time(long) of the object that was created or None if
the object does not have one, meaning it has not been persisted.
"""
return self._created
@abc.abstractproperty
def format(self):
"""Returns the encoding format.

View File

@ -25,13 +25,13 @@ from castellan.common.objects import managed_object
class OpaqueData(managed_object.ManagedObject):
"""This class represents opaque data."""
def __init__(self, data, name=None):
def __init__(self, data, name=None, created=None):
"""Create a new OpaqueData object.
Expected type for data is a bytestring.
"""
self._data = data
super(OpaqueData, self).__init__(name=name)
super(OpaqueData, self).__init__(name=name, created=created)
@property
def format(self):
@ -44,8 +44,7 @@ class OpaqueData(managed_object.ManagedObject):
def __eq__(self, other):
if isinstance(other, OpaqueData):
return (self._data == other._data and
self._name == other._name)
return (self._data == other._data)
else:
return False

View File

@ -25,13 +25,13 @@ from castellan.common.objects import managed_object
class Passphrase(managed_object.ManagedObject):
"""This class represents a passphrase."""
def __init__(self, passphrase, name=None):
def __init__(self, passphrase, name=None, created=None):
"""Create a new Passphrase object.
The expected type for the passphrase is a bytestring.
"""
self._passphrase = passphrase
super(Passphrase, self).__init__(name=name)
super(Passphrase, self).__init__(name=name, created=created)
@property
def format(self):
@ -44,8 +44,7 @@ class Passphrase(managed_object.ManagedObject):
def __eq__(self, other):
if isinstance(other, Passphrase):
return (self._passphrase == other._passphrase and
self._name == other._name)
return (self._passphrase == other._passphrase)
else:
return False

View File

@ -25,7 +25,8 @@ from castellan.common.objects import key
class PrivateKey(key.Key):
"""This class represents private keys."""
def __init__(self, algorithm, bit_length, key, name=None):
def __init__(self, algorithm, bit_length, key,
name=None, created=None):
"""Create a new PrivateKey object.
The arguments specify the algorithm and bit length for the asymmetric
@ -34,7 +35,7 @@ class PrivateKey(key.Key):
self._alg = algorithm
self._bit_length = bit_length
self._key = key
super(PrivateKey, self).__init__(name=name)
super(PrivateKey, self).__init__(name=name, created=created)
@property
def algorithm(self):
@ -59,8 +60,7 @@ class PrivateKey(key.Key):
if isinstance(other, PrivateKey):
return (self._alg == other._alg and
self._bit_length == other._bit_length and
self._key == other._key and
self._name == other._name)
self._key == other._key)
else:
return False

View File

@ -25,7 +25,8 @@ from castellan.common.objects import key
class PublicKey(key.Key):
"""This class represents public keys."""
def __init__(self, algorithm, bit_length, key, name=None):
def __init__(self, algorithm, bit_length, key,
name=None, created=None):
"""Create a new PublicKey object.
The arguments specify the algorithm and bit length for the asymmetric
@ -35,7 +36,7 @@ class PublicKey(key.Key):
self._alg = algorithm
self._bit_length = bit_length
self._key = key
super(PublicKey, self).__init__(name=name)
super(PublicKey, self).__init__(name=name, created=created)
@property
def algorithm(self):
@ -60,8 +61,7 @@ class PublicKey(key.Key):
if isinstance(other, PublicKey):
return (self._alg == other._alg and
self._bit_length == other._bit_length and
self._key == other._key and
self._name == other._name)
self._key == other._key)
else:
return False

View File

@ -25,7 +25,8 @@ from castellan.common.objects import key
class SymmetricKey(key.Key):
"""This class represents symmetric keys."""
def __init__(self, algorithm, bit_length, key, name=None):
def __init__(self, algorithm, bit_length, key,
name=None, created=None):
"""Create a new SymmetricKey object.
The arguments specify the algorithm and bit length for the symmetric
@ -34,7 +35,7 @@ class SymmetricKey(key.Key):
self._alg = algorithm
self._bit_length = bit_length
self._key = key
super(SymmetricKey, self).__init__(name=name)
super(SymmetricKey, self).__init__(name=name, created=created)
@property
def algorithm(self):
@ -59,8 +60,7 @@ class SymmetricKey(key.Key):
if isinstance(other, SymmetricKey):
return (self._alg == other._alg and
self._bit_length == other._bit_length and
self._key == other._key and
self._name == other._name)
self._key == other._key)
else:
return False

View File

@ -25,13 +25,13 @@ from castellan.common.objects import certificate
class X509(certificate.Certificate):
"""This class represents X.509 certificates."""
def __init__(self, data, name=None):
def __init__(self, data, name=None, created=None):
"""Create a new X509 object.
The data should be in a bytestring.
"""
self._data = data
super(X509, self).__init__(name=name)
super(X509, self).__init__(name=name, created=created)
@property
def format(self):
@ -44,8 +44,7 @@ class X509(certificate.Certificate):
def __eq__(self, other):
if isinstance(other, X509):
return (self._data == other._data and
self._name == other._name)
return (self._data == other._data)
else:
return False

View File

@ -16,6 +16,7 @@
"""
Key manager implementation for Barbican
"""
import calendar
import time
from cryptography.hazmat import backends
@ -40,8 +41,10 @@ from castellan.openstack.common import _i18n as u
from barbicanclient import client as barbican_client
from barbicanclient import exceptions as barbican_exceptions
from oslo_utils import timeutils
from six.moves import urllib
barbican_opts = [
cfg.StrOpt('barbican_endpoint',
help='Use this endpoint to connect to Barbican, for example: '
@ -421,14 +424,22 @@ class BarbicanKeyManager(key_manager.KeyManager):
secret_data = self._get_secret_data(secret)
# convert created ISO8601 in Barbican to POSIX
if secret.created:
time_stamp = timeutils.parse_isotime(
str(secret.created)).timetuple()
created = calendar.timegm(time_stamp)
if issubclass(secret_type, key_base_class.Key):
return secret_type(secret.algorithm,
secret.bit_length,
secret_data,
secret.name)
secret.name,
created)
else:
return secret_type(secret_data,
secret.name)
secret.name,
created)
def _get_secret(self, context, object_id):
"""Returns the metadata of the secret.

View File

@ -16,10 +16,12 @@
"""
Test cases for the barbican key manager.
"""
import calendar
from barbicanclient import exceptions as barbican_exceptions
import mock
from oslo_config import cfg
from oslo_utils import timeutils
from castellan.common import exception
from castellan.common.objects import symmetric_key as sym_key
@ -187,6 +189,11 @@ class BarbicanKeyManagerTestCase(test_key_manager.KeyManagerTestCase):
original_secret_metadata.bit_length = mock.sentinel.bit
original_secret_metadata.secret_type = 'symmetric'
created = timeutils.parse_isotime('2015-10-20 18:51:17+00:00')
original_secret_metadata.created = created
created_formatted = timeutils.parse_isotime(str(created))
created_posix = calendar.timegm(created_formatted.timetuple())
key_name = 'my key'
original_secret_metadata.name = key_name
@ -199,6 +206,7 @@ class BarbicanKeyManagerTestCase(test_key_manager.KeyManagerTestCase):
self.get.assert_called_once_with(self.secret_ref)
self.assertEqual(key_name, key.name)
self.assertEqual(original_secret_data, key.get_encoded())
self.assertEqual(created_posix, key.created)
def test_get_null_context(self):
self.key_mgr._barbican_client = None

View File

@ -16,7 +16,6 @@
"""
Test cases for the opaque data class.
"""
from castellan.common.objects import opaque_data
from castellan.tests import base
@ -24,11 +23,14 @@ from castellan.tests import base
class OpaqueDataTestCase(base.TestCase):
def _create_data(self):
return opaque_data.OpaqueData(self.data, self.name)
return opaque_data.OpaqueData(self.data,
self.name,
self.created)
def setUp(self):
self.data = bytes(b"secret opaque data")
self.name = 'my opaque'
self.created = 1448088699
self.opaque_data = self._create_data()
super(OpaqueDataTestCase, self).setUp()
@ -42,6 +44,17 @@ class OpaqueDataTestCase(base.TestCase):
def test_get_name(self):
self.assertEqual(self.name, self.opaque_data.name)
def test_get_created(self):
self.assertEqual(self.created, self.opaque_data.created)
def test_get_created_none(self):
created = None
data = opaque_data.OpaqueData(self.data,
self.name,
created)
self.assertEqual(created, data.created)
def test___eq__(self):
self.assertTrue(self.opaque_data == self.opaque_data)
self.assertTrue(self.opaque_data is self.opaque_data)
@ -49,7 +62,7 @@ class OpaqueDataTestCase(base.TestCase):
self.assertFalse(self.opaque_data is None)
self.assertFalse(None == self.opaque_data)
other_opaque_data = opaque_data.OpaqueData(self.data, self.name)
other_opaque_data = opaque_data.OpaqueData(self.data)
self.assertTrue(self.opaque_data == other_opaque_data)
self.assertFalse(self.opaque_data is other_opaque_data)
@ -60,7 +73,3 @@ class OpaqueDataTestCase(base.TestCase):
def test___ne___data(self):
other_opaque = opaque_data.OpaqueData(b'other data', self.name)
self.assertTrue(self.opaque_data != other_opaque)
def test___ne___name(self):
other_opaque = opaque_data.OpaqueData(self.data, "other opaque")
self.assertTrue(self.opaque_data != other_opaque)

View File

@ -16,7 +16,6 @@
"""
Test cases for the passphrase class.
"""
from castellan.common.objects import passphrase
from castellan.tests import base
@ -25,11 +24,13 @@ class PassphraseTestCase(base.TestCase):
def _create_passphrase(self):
return passphrase.Passphrase(self.passphrase_data,
self.name)
self.name,
self.created)
def setUp(self):
self.passphrase_data = bytes(b"secret passphrase")
self.name = 'my phrase'
self.created = 1448088699
self.passphrase = self._create_passphrase()
super(PassphraseTestCase, self).setUp()
@ -43,6 +44,17 @@ class PassphraseTestCase(base.TestCase):
def test_get_name(self):
self.assertEqual(self.name, self.passphrase.name)
def test_get_created(self):
self.assertEqual(self.created, self.passphrase.created)
def test_get_created_none(self):
created = None
phrase = passphrase.Passphrase(self.passphrase_data,
self.name,
created)
self.assertEqual(created, phrase.created)
def test___eq__(self):
self.assertTrue(self.passphrase == self.passphrase)
self.assertTrue(self.passphrase is self.passphrase)
@ -50,8 +62,7 @@ class PassphraseTestCase(base.TestCase):
self.assertFalse(self.passphrase is None)
self.assertFalse(None == self.passphrase)
other_passphrase = passphrase.Passphrase(self.passphrase_data,
self.name)
other_passphrase = passphrase.Passphrase(self.passphrase_data)
self.assertTrue(self.passphrase == other_passphrase)
self.assertFalse(self.passphrase is other_passphrase)
@ -62,8 +73,3 @@ class PassphraseTestCase(base.TestCase):
def test___ne___data(self):
other_phrase = passphrase.Passphrase(b"other passphrase", self.name)
self.assertTrue(self.passphrase != other_phrase)
def test___ne__name(self):
other_phrase = passphrase.Passphrase(self.passphrase_data,
"other phrase")
self.assertTrue(self.passphrase != other_phrase)

View File

@ -16,7 +16,6 @@
"""
Test cases for the private key class.
"""
from castellan.common.objects import private_key
from castellan.tests import base
from castellan.tests import utils
@ -26,23 +25,25 @@ class PrivateKeyTestCase(base.KeyTestCase):
def _create_key(self):
return private_key.PrivateKey(self.algorithm,
self.length,
self.bit_length,
self.encoded,
self.name)
self.name,
self.created)
def setUp(self):
self.algorithm = 'RSA'
self.length = 2048
self.bit_length = 2048
self.encoded = bytes(utils.get_private_key_der())
self.name = 'my key'
self.created = 1448088699
super(PrivateKeyTestCase, self).setUp()
def test_get_algorithm(self):
self.assertEqual(self.algorithm, self.key.algorithm)
def test_get_length(self):
self.assertEqual(self.length, self.key.bit_length)
def test_get_bit_length(self):
self.assertEqual(self.bit_length, self.key.bit_length)
def test_get_name(self):
self.assertEqual(self.name, self.key.name)
@ -53,6 +54,19 @@ class PrivateKeyTestCase(base.KeyTestCase):
def test_get_encoded(self):
self.assertEqual(self.encoded, self.key.get_encoded())
def test_get_created(self):
self.assertEqual(self.created, self.key.created)
def test_get_created_none(self):
created = None
key = private_key.PrivateKey(self.algorithm,
self.bit_length,
self.encoded,
self.name,
created)
self.assertEqual(created, key.created)
def test___eq__(self):
self.assertTrue(self.key == self.key)
self.assertTrue(self.key is self.key)
@ -61,9 +75,8 @@ class PrivateKeyTestCase(base.KeyTestCase):
self.assertFalse(None == self.key)
other_key = private_key.PrivateKey(self.algorithm,
self.length,
self.encoded,
self.name)
self.bit_length,
self.encoded)
self.assertTrue(self.key == other_key)
self.assertFalse(self.key is other_key)
@ -73,12 +86,12 @@ class PrivateKeyTestCase(base.KeyTestCase):
def test___ne___algorithm(self):
other_key = private_key.PrivateKey('DSA',
self.length,
self.bit_length,
self.encoded,
self.name)
self.assertTrue(self.key != other_key)
def test___ne___length(self):
def test___ne___bit_length(self):
other_key = private_key.PrivateKey(self.algorithm,
4096,
self.encoded,
@ -88,14 +101,7 @@ class PrivateKeyTestCase(base.KeyTestCase):
def test___ne___encoded(self):
different_encoded = bytes(utils.get_private_key_der()) + b'\x00'
other_key = private_key.PrivateKey(self.algorithm,
self.length,
self.bit_length,
different_encoded,
self.name)
self.assertTrue(self.key != other_key)
def test___ne___name(self):
other_key = private_key.PrivateKey(self.algorithm,
self.length,
self.encoded,
'other key')
self.assertTrue(self.key != other_key)

View File

@ -16,7 +16,6 @@
"""
Test cases for the public key class.
"""
from castellan.common.objects import public_key
from castellan.tests import base
from castellan.tests import utils
@ -26,23 +25,25 @@ class PublicKeyTestCase(base.KeyTestCase):
def _create_key(self):
return public_key.PublicKey(self.algorithm,
self.length,
self.bit_length,
self.encoded,
self.name)
self.name,
self.created)
def setUp(self):
self.algorithm = 'RSA'
self.length = 2048
self.bit_length = 2048
self.encoded = bytes(utils.get_public_key_der())
self.name = 'my key'
self.created = 1448088699
super(PublicKeyTestCase, self).setUp()
def test_get_algorithm(self):
self.assertEqual(self.algorithm, self.key.algorithm)
def test_get_length(self):
self.assertEqual(self.length, self.key.bit_length)
def test_get_bit_length(self):
self.assertEqual(self.bit_length, self.key.bit_length)
def test_get_name(self):
self.assertEqual(self.name, self.key.name)
@ -53,6 +54,19 @@ class PublicKeyTestCase(base.KeyTestCase):
def test_get_encoded(self):
self.assertEqual(self.encoded, self.key.get_encoded())
def test_get_created(self):
self.assertEqual(self.created, self.key.created)
def test_get_created_none(self):
created = None
key = public_key.PublicKey(self.algorithm,
self.bit_length,
self.encoded,
self.name,
created)
self.assertEqual(created, key.created)
def test___eq__(self):
self.assertTrue(self.key == self.key)
self.assertTrue(self.key is self.key)
@ -61,9 +75,8 @@ class PublicKeyTestCase(base.KeyTestCase):
self.assertFalse(None == self.key)
other_key = public_key.PublicKey(self.algorithm,
self.length,
self.encoded,
self.name)
self.bit_length,
self.encoded)
self.assertTrue(self.key == other_key)
self.assertFalse(self.key is other_key)
@ -73,12 +86,12 @@ class PublicKeyTestCase(base.KeyTestCase):
def test___ne___algorithm(self):
other_key = public_key.PublicKey('DSA',
self.length,
self.bit_length,
self.encoded,
self.name)
self.assertTrue(self.key != other_key)
def test___ne___length(self):
def test___ne___bit_length(self):
other_key = public_key.PublicKey(self.algorithm,
4096,
self.encoded,
@ -88,14 +101,7 @@ class PublicKeyTestCase(base.KeyTestCase):
def test___ne___encoded(self):
different_encoded = bytes(utils.get_public_key_der()) + b'\x00'
other_key = public_key.PublicKey(self.algorithm,
self.length,
self.bit_length,
different_encoded,
self.name)
self.assertTrue(self.key != other_key)
def test___ne__name(self):
other_key = public_key.PublicKey(self.algorithm,
self.length,
self.encoded,
'other key')
self.assertTrue(self.key != other_key)

View File

@ -16,7 +16,6 @@
"""
Test cases for the symmetric key class.
"""
from castellan.common.objects import symmetric_key as sym_key
from castellan.tests import base
@ -27,13 +26,15 @@ class SymmetricKeyTestCase(base.KeyTestCase):
return sym_key.SymmetricKey(self.algorithm,
self.bit_length,
self.encoded,
self.name)
self.name,
self.created)
def setUp(self):
self.algorithm = 'AES'
self.encoded = bytes(b'0' * 64)
self.bit_length = len(self.encoded) * 8
self.name = 'my key'
self.created = 1448088699
super(SymmetricKeyTestCase, self).setUp()
@ -52,6 +53,19 @@ class SymmetricKeyTestCase(base.KeyTestCase):
def test_get_bit_length(self):
self.assertEqual(self.bit_length, self.key.bit_length)
def test_get_created(self):
self.assertEqual(self.created, self.key.created)
def test_get_created_none(self):
created = None
key = sym_key.SymmetricKey(self.algorithm,
self.bit_length,
self.encoded,
self.name,
created)
self.assertEqual(created, key.created)
def test___eq__(self):
self.assertTrue(self.key == self.key)
self.assertTrue(self.key is self.key)
@ -61,8 +75,7 @@ class SymmetricKeyTestCase(base.KeyTestCase):
other_key = sym_key.SymmetricKey(self.algorithm,
self.bit_length,
self.encoded,
self.name)
self.encoded)
self.assertTrue(self.key == other_key)
self.assertFalse(self.key is other_key)
@ -77,7 +90,7 @@ class SymmetricKeyTestCase(base.KeyTestCase):
self.name)
self.assertTrue(self.key != other_key)
def test___ne___length(self):
def test___ne___bit_length(self):
other_key = sym_key.SymmetricKey(self.algorithm,
self.bit_length * 2,
self.encoded,
@ -91,10 +104,3 @@ class SymmetricKeyTestCase(base.KeyTestCase):
different_encoded,
self.name)
self.assertTrue(self.key != other_key)
def test___ne___name(self):
other_key = sym_key.SymmetricKey(self.algorithm,
self.bit_length,
self.encoded,
'other key')
self.assertTrue(self.key != other_key)

View File

@ -16,7 +16,6 @@
"""
Test cases for the X.509 certificate class.
"""
from castellan.common.objects import x_509
from castellan.tests import base
from castellan.tests import utils
@ -25,11 +24,14 @@ from castellan.tests import utils
class X509TestCase(base.CertificateTestCase):
def _create_cert(self):
return x_509.X509(self.data, self.name)
return x_509.X509(self.data,
self.name,
self.created)
def setUp(self):
self.data = utils.get_certificate_der()
self.name = 'my cert'
self.created = 1448088699
super(X509TestCase, self).setUp()
@ -42,6 +44,17 @@ class X509TestCase(base.CertificateTestCase):
def test_get_encoded(self):
self.assertEqual(self.data, self.cert.get_encoded())
def test_get_created(self):
self.assertEqual(self.created, self.cert.created)
def test_get_created_none(self):
created = None
cert = x_509.X509(self.data,
self.name,
created)
self.assertEqual(created, cert.created)
def test___eq__(self):
self.assertTrue(self.cert == self.cert)
self.assertTrue(self.cert is self.cert)
@ -49,7 +62,7 @@ class X509TestCase(base.CertificateTestCase):
self.assertFalse(self.cert is None)
self.assertFalse(None == self.cert)
other_x_509 = x_509.X509(self.data, self.name)
other_x_509 = x_509.X509(self.data)
self.assertTrue(self.cert == other_x_509)
self.assertFalse(self.cert is other_x_509)
@ -60,7 +73,3 @@ class X509TestCase(base.CertificateTestCase):
def test___ne___data(self):
other_x509 = x_509.X509(b'\x00\x00\x00', self.name)
self.assertTrue(self.cert != other_x509)
def test___ne__name(self):
other_x509 = x_509.X509(self.data, "other x509")
self.assertTrue(self.cert != other_x509)