c21f07634b
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.
165 lines
5.4 KiB
Python
165 lines
5.4 KiB
Python
# Copyright (c) 2016 The Johns Hopkins University/Applied Physics Laboratory
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from kmip.core import enums
|
|
from sqlalchemy import Column, ForeignKey, Integer, String
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import relationship
|
|
|
|
import sqlalchemy.types as types
|
|
|
|
|
|
Base = declarative_base()
|
|
|
|
|
|
def attribute_append_factory(index_attribute):
|
|
def attribute_append(list_container, list_attribute, initiator):
|
|
index = getattr(list_container, index_attribute)
|
|
list_attribute.index = index
|
|
setattr(list_container, index_attribute, index + 1)
|
|
return list_attribute
|
|
return attribute_append
|
|
|
|
|
|
class UsageMaskType(types.TypeDecorator):
|
|
"""
|
|
Converts a list of enums.CryptographicUsageMask Enums in an integer
|
|
bitmask. This allows the database to only store an integer instead of a
|
|
list of enumbs. This also does the reverse of converting an integer bit
|
|
mask into a list enums.CryptographicUsageMask Enums.
|
|
"""
|
|
|
|
impl = types.Integer
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
"""
|
|
Returns the integer value of the usage mask bitmask. This value is
|
|
stored in the database.
|
|
|
|
Args:
|
|
value(list<enums.CryptographicUsageMask>): list of enums in the
|
|
usage mask
|
|
dialect(string): SQL dialect
|
|
"""
|
|
bitmask = 0x00
|
|
for e in value:
|
|
bitmask = bitmask | e.value
|
|
return bitmask
|
|
|
|
def process_result_value(self, value, dialect):
|
|
"""
|
|
Returns a new list of enums.CryptographicUsageMask Enums. This converts
|
|
the integer value into the list of enums.
|
|
|
|
Args:
|
|
value(int): The integer value stored in the database that is used
|
|
to create the list of enums.CryptographicUsageMask Enums.
|
|
dialect(string): SQL dialect
|
|
"""
|
|
masks = list()
|
|
if value:
|
|
for e in enums.CryptographicUsageMask:
|
|
if e.value & value:
|
|
masks.append(e)
|
|
return masks
|
|
|
|
|
|
class EnumType(types.TypeDecorator):
|
|
"""
|
|
Converts a Python enum to an integer before storing it in the database.
|
|
This also does the reverse of converting an integer into an enum object.
|
|
This allows enums to be stored in a database.
|
|
"""
|
|
|
|
impl = types.Integer
|
|
|
|
def __init__(self, cls):
|
|
"""
|
|
Create a new EnumType. This new EnumType requires a class object in the
|
|
constructor. The class is used to construct new instances of the Enum
|
|
when the integer value is retrieved from the database.
|
|
|
|
Args:
|
|
cls(class): An Enum class used to create new instances from integer
|
|
values.
|
|
"""
|
|
super(EnumType, self).__init__()
|
|
self._cls = cls
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
"""
|
|
Returns the integer value of the Enum. This value is stored in the
|
|
database.
|
|
|
|
Args:
|
|
value(Enum): An Enum instance whose integer value is to be stored.
|
|
dialect(string): SQL dialect
|
|
"""
|
|
return value.value
|
|
|
|
def process_result_value(self, value, dialect):
|
|
"""
|
|
Returns a new Enum representing the value stored in the database. The
|
|
Enum class type of the returned object is that of the cls parameter in
|
|
the __init__ call.
|
|
|
|
Args:
|
|
value(int): The integer value stored in the database that is used
|
|
to create the Enum
|
|
dialect(string): SQL dialect
|
|
"""
|
|
return self._cls(value)
|
|
|
|
|
|
class ManagedObjectName(Base):
|
|
|
|
__tablename__ = 'managed_object_names'
|
|
id = Column('id', Integer, primary_key=True)
|
|
mo_uid = Column('mo_uid', Integer, ForeignKey('managed_objects.uid'))
|
|
name = Column('name', String)
|
|
index = Column('name_index', Integer)
|
|
name_type = Column('name_type', EnumType(enums.NameType))
|
|
|
|
mo = relationship('ManagedObject', back_populates='_names')
|
|
|
|
def __init__(self, name, index=0,
|
|
name_type=enums.NameType.UNINTERPRETED_TEXT_STRING):
|
|
self.name = name
|
|
self.index = index
|
|
self.name_type = name_type
|
|
|
|
def __repr__(self):
|
|
return ("<ManagedObjectName(name='%s', index='%d', type='%s')>" %
|
|
(self.name, self.index, self.name_type))
|
|
|
|
def __eq__(self, other):
|
|
if isinstance(other, ManagedObjectName):
|
|
if self.name != other.name:
|
|
return False
|
|
elif self.index != other.index:
|
|
return False
|
|
elif self.name_type != other.name_type:
|
|
return False
|
|
else:
|
|
return True
|
|
else:
|
|
return NotImplemented
|
|
|
|
def __ne__(self, other):
|
|
if isinstance(other, ManagedObjectName):
|
|
return not (self == other)
|
|
else:
|
|
return NotImplemented
|