2
0
mirror of https://github.com/openkmip/pykmip synced 2025-12-20 10:13:18 +00:00

Added SQLAlchemy Code for Symmetric Key

The code for persisting symmetric keys in a database has been added
along with the corresponding unit tests.

The usage mask list for cryptographic objects is stored as an integer bitmask.
The conversion takes place with a new SQLAlchemy type.

Switched ManagedObject value type to VARBINARY. This prevents errors from
occuring when trying to convert to a string.
This commit is contained in:
Nathan Reller
2016-02-16 15:59:49 -05:00
parent 4d6caf1de7
commit c21f07634b
3 changed files with 406 additions and 55 deletions

View File

@@ -14,7 +14,7 @@
# under the License.
from abc import abstractmethod
from sqlalchemy import Column, event, ForeignKey, Integer, VARCHAR
from sqlalchemy import Column, event, ForeignKey, Integer, VARBINARY
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import relationship
@@ -46,7 +46,7 @@ class ManagedObject(sql.Base):
__tablename__ = 'managed_objects'
unique_identifier = Column('uid', Integer, primary_key=True)
_object_type = Column('object_type', sql.EnumType(enums.ObjectType))
value = Column('value', VARCHAR(1024))
value = Column('value', VARBINARY(1024))
name_index = Column(Integer, default=0)
_names = relationship('ManagedObjectName', back_populates='mo',
cascade='all, delete-orphan')
@@ -142,6 +142,16 @@ class CryptographicObject(ManagedObject):
describing how the CryptographicObject will be used.
"""
__tablename__ = 'crypto_objects'
unique_identifier = Column('uid', Integer,
ForeignKey('managed_objects.uid'),
primary_key=True)
cryptographic_usage_masks = Column('cryptographic_usage_mask',
sql.UsageMaskType)
__mapper_args__ = {
'polymorphic_identity': 0x80000001
}
@abstractmethod
def __init__(self):
"""
@@ -188,6 +198,20 @@ class Key(CryptographicObject):
the key value.
"""
__tablename__ = 'keys'
unique_identifier = Column('uid', Integer,
ForeignKey('crypto_objects.uid'),
primary_key=True)
cryptographic_algorithm = Column(
'cryptographic_algorithm', sql.EnumType(enums.CryptographicAlgorithm))
cryptographic_length = Column('cryptographic_length', Integer)
key_format_type = Column(
'key_format_type', sql.EnumType(enums.KeyFormatType))
__mapper_args__ = {
'polymorphic_identity': 0x80000002
}
@abstractmethod
def __init__(self):
"""
@@ -226,6 +250,15 @@ class SymmetricKey(Key):
names: The string names of the SymmetricKey.
"""
__tablename__ = 'symmetric_keys'
unique_identifier = Column('uid', Integer,
ForeignKey('keys.uid'),
primary_key=True)
__mapper_args__ = {
'polymorphic_identity': enums.ObjectType.SYMMETRIC_KEY
}
def __init__(self, algorithm, length, value, masks=None,
name='Symmetric Key'):
"""
@@ -252,9 +285,7 @@ class SymmetricKey(Key):
self.names = [name]
if masks:
self.cryptographic_usage_masks = masks
else:
self.cryptographic_usage_masks = list()
self.cryptographic_usage_masks.extend(masks)
# All remaining attributes are not considered part of the public API
# and are subject to change.
@@ -282,8 +313,6 @@ class SymmetricKey(Key):
"enumeration")
elif not isinstance(self.cryptographic_length, six.integer_types):
raise TypeError("key length must be an integer")
elif not isinstance(self.cryptographic_usage_masks, list):
raise TypeError("key usage masks must be a list")
mask_count = len(self.cryptographic_usage_masks)
for i in range(mask_count):
@@ -337,6 +366,10 @@ class SymmetricKey(Key):
return NotImplemented
event.listen(SymmetricKey._names, 'append',
sql.attribute_append_factory("name_index"), retval=False)
class PublicKey(Key):
"""
The PublicKey class of the simplified KMIP object hierarchy.
@@ -389,8 +422,6 @@ class PublicKey(Key):
if masks:
self.cryptographic_usage_masks = masks
else:
self.cryptographic_usage_masks = list()
# All remaining attributes are not considered part of the public API
# and are subject to change.
@@ -422,8 +453,6 @@ class PublicKey(Key):
elif self.key_format_type not in self._valid_formats:
raise ValueError("key format type must be one of {0}".format(
self._valid_formats))
elif not isinstance(self.cryptographic_usage_masks, list):
raise TypeError("key usage masks must be a list")
# TODO (peter-hamilton) Verify that the key bytes match the key format
@@ -529,8 +558,6 @@ class PrivateKey(Key):
if masks:
self.cryptographic_usage_masks = masks
else:
self.cryptographic_usage_masks = list()
# All remaining attributes are not considered part of the public API
# and are subject to change.
@@ -562,8 +589,6 @@ class PrivateKey(Key):
elif self.key_format_type not in self._valid_formats:
raise ValueError("key format type must be one of {0}".format(
self._valid_formats))
elif not isinstance(self.cryptographic_usage_masks, list):
raise TypeError("key usage masks must be a list")
# TODO (peter-hamilton) Verify that the key bytes match the key format
@@ -658,8 +683,6 @@ class Certificate(CryptographicObject):
if masks:
self.cryptographic_usage_masks = masks
else:
self.cryptographic_usage_masks = list()
# All remaining attributes are not considered part of the public API
# and are subject to change.
@@ -687,8 +710,6 @@ class Certificate(CryptographicObject):
enums.CertificateTypeEnum):
raise TypeError("certificate type must be a CertificateTypeEnum "
"enumeration")
elif not isinstance(self.cryptographic_usage_masks, list):
raise TypeError("certificate usage masks must be a list")
mask_count = len(self.cryptographic_usage_masks)
for i in range(mask_count):
@@ -808,8 +829,6 @@ class SecretData(CryptographicObject):
if masks:
self.cryptographic_usage_masks = masks
else:
self.cryptographic_usage_masks = list()
# All remaining attributes are not considered part of the public API
# and are subject to change.
@@ -831,8 +850,6 @@ class SecretData(CryptographicObject):
elif not isinstance(self.data_type, enums.SecretDataType):
raise TypeError("secret data type must be a SecretDataType "
"enumeration")
elif not isinstance(self.cryptographic_usage_masks, list):
raise TypeError("secret data usage masks must be a list")
mask_count = len(self.cryptographic_usage_masks)
for i in range(mask_count):