mirror of https://github.com/OpenKMIP/PyKMIP.git
Adding opaque objects to the Pie object hierarchy
This change adds an OpaqueObject class to the Pie object hierarchy. A unit test suite covering the class is included, as are updates to the Pie object factory and associated tests.
This commit is contained in:
parent
13dfa14416
commit
93610719a5
|
@ -64,6 +64,10 @@ class ObjectFactory:
|
|||
return self._build_core_secret_data(obj)
|
||||
elif isinstance(obj, secrets.SecretData):
|
||||
return self._build_pie_secret_data(obj)
|
||||
elif isinstance(obj, pobjects.OpaqueObject):
|
||||
return self._build_core_opaque_object(obj)
|
||||
elif isinstance(obj, secrets.OpaqueObject):
|
||||
return self._build_pie_opaque_object(obj)
|
||||
else:
|
||||
raise TypeError("object type unsupported and cannot be converted")
|
||||
|
||||
|
@ -94,15 +98,17 @@ class ObjectFactory:
|
|||
else:
|
||||
return cls(algorithm, length, value, format_type)
|
||||
|
||||
def _build_core_certificate(self, cert):
|
||||
return secrets.Certificate(cert.certificate_type, cert.value)
|
||||
|
||||
def _build_pie_secret_data(self, secret):
|
||||
secret_data_type = secret.secret_data_type.enum
|
||||
value = secret.key_block.key_value.key_material.value
|
||||
|
||||
return pobjects.SecretData(value, secret_data_type)
|
||||
|
||||
def _build_pie_opaque_object(self, obj):
|
||||
opaque_type = obj.opaque_data_type.enum
|
||||
value = obj.opaque_data_value.value
|
||||
return pobjects.OpaqueObject(value, opaque_type)
|
||||
|
||||
def _build_core_key(self, key, cls):
|
||||
algorithm = key.cryptographic_algorithm
|
||||
length = key.cryptographic_length
|
||||
|
@ -122,6 +128,9 @@ class ObjectFactory:
|
|||
|
||||
return cls(key_block)
|
||||
|
||||
def _build_core_certificate(self, cert):
|
||||
return secrets.Certificate(cert.certificate_type, cert.value)
|
||||
|
||||
def _build_core_secret_data(self, secret):
|
||||
secret_data_type = secret.data_type
|
||||
value = secret.value
|
||||
|
@ -138,3 +147,11 @@ class ObjectFactory:
|
|||
data_type = secrets.SecretData.SecretDataType(secret_data_type)
|
||||
|
||||
return secrets.SecretData(data_type, key_block)
|
||||
|
||||
def _build_core_opaque_object(self, obj):
|
||||
opaque_type = obj.opaque_type
|
||||
value = obj.value
|
||||
|
||||
opaque_data_type = secrets.OpaqueObject.OpaqueDataType(opaque_type)
|
||||
opaque_data_value = secrets.OpaqueObject.OpaqueDataValue(value)
|
||||
return secrets.OpaqueObject(opaque_data_type, opaque_data_value)
|
||||
|
|
|
@ -859,3 +859,94 @@ class SecretData(CryptographicObject):
|
|||
return not (self == other)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class OpaqueObject(ManagedObject):
|
||||
"""
|
||||
The OpaqueObject class of the simplified KMIP object hierarchy.
|
||||
|
||||
OpaqueObject is one of several ManagedObjects and is one of the core KMIP
|
||||
objects that are the subject of key management operations. For more
|
||||
information, see Section 2.2 of the KMIP 1.1 specification.
|
||||
|
||||
Attributes:
|
||||
opaque_type: The type of the opaque value.
|
||||
"""
|
||||
|
||||
def __init__(self, value, opaque_type, name='Opaque Object'):
|
||||
"""
|
||||
Create a OpaqueObject.
|
||||
|
||||
Args:
|
||||
value(bytes): The bytes representing opaque data.
|
||||
opaque_type(OpaqueDataType): An enumeration defining the type of
|
||||
the opaque value.
|
||||
name(string): The string name of the opaque object.
|
||||
"""
|
||||
super(OpaqueObject, self).__init__()
|
||||
|
||||
self._object_type = enums.ObjectType.OPAQUE_DATA
|
||||
|
||||
self.value = value
|
||||
self.opaque_type = opaque_type
|
||||
self.names = [name]
|
||||
|
||||
# All remaining attributes are not considered part of the public API
|
||||
# and are subject to change.
|
||||
self._digest = None
|
||||
self._revocation_reason = None
|
||||
|
||||
# The following attributes are placeholders for attributes that are
|
||||
# unsupported by kmip.core
|
||||
self._destroy_date = None
|
||||
self._compromise_occurrence_date = None
|
||||
self._compromise_date = None
|
||||
|
||||
self.validate()
|
||||
|
||||
def validate(self):
|
||||
"""
|
||||
Verify that the contents of the OpaqueObject are valid.
|
||||
|
||||
Raises:
|
||||
TypeError: if the types of any OpaqueObject attributes are invalid.
|
||||
"""
|
||||
if not isinstance(self.value, bytes):
|
||||
raise TypeError("opaque value must be bytes")
|
||||
elif not isinstance(self.opaque_type, enums.OpaqueDataType):
|
||||
raise TypeError("opaque data type must be an OpaqueDataType "
|
||||
"enumeration")
|
||||
|
||||
name_count = len(self.names)
|
||||
for i in range(name_count):
|
||||
name = self.names[i]
|
||||
if not isinstance(name, six.string_types):
|
||||
position = "({0} in list)".format(i)
|
||||
raise TypeError("opaque data name {0} must be a string".format(
|
||||
position))
|
||||
|
||||
def __repr__(self):
|
||||
value = "value={0}".format(binascii.hexlify(self.value))
|
||||
opaque_type = "opaque_type={0}".format(self.opaque_type)
|
||||
|
||||
return "OpaqueObject({0}, {1})".format(value, opaque_type)
|
||||
|
||||
def __str__(self):
|
||||
return str(binascii.hexlify(self.value))
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, OpaqueObject):
|
||||
if self.value != other.value:
|
||||
return False
|
||||
elif self.opaque_type != other.opaque_type:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
if isinstance(other, OpaqueObject):
|
||||
return not (self == other)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
# Copyright (c) 2015 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.
|
||||
|
||||
import binascii
|
||||
import testtools
|
||||
|
||||
from kmip.core import enums
|
||||
from kmip.pie import objects
|
||||
|
||||
|
||||
class TestOpaqueObject(testtools.TestCase):
|
||||
"""
|
||||
Test suite for OpaqueObject.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestOpaqueObject, self).setUp()
|
||||
|
||||
# Encoding taken from Sections 3.1.5 of the KMIP 1.1 testing
|
||||
# documentation.
|
||||
self.bytes_a = (
|
||||
b'\x53\x65\x63\x72\x65\x74\x50\x61\x73\x73\x77\x6F\x72\x64')
|
||||
self.bytes_b = (
|
||||
b'\x53\x65\x63\x72\x65\x74\x50\x61\x73\x73\x77\x6F\x72\x65')
|
||||
|
||||
def tearDown(self):
|
||||
super(TestOpaqueObject, self).tearDown()
|
||||
|
||||
def test_init(self):
|
||||
"""
|
||||
Test that a OpaqueObject object can be instantiated.
|
||||
"""
|
||||
obj = objects.OpaqueObject(
|
||||
self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
|
||||
self.assertEqual(obj.value, self.bytes_a)
|
||||
self.assertEqual(obj.opaque_type, enums.OpaqueDataType.NONE)
|
||||
self.assertEqual(obj.names, ['Opaque Object'])
|
||||
|
||||
def test_init_with_args(self):
|
||||
"""
|
||||
Test that a OpaqueObject object can be instantiated with all arguments.
|
||||
"""
|
||||
obj = objects.OpaqueObject(
|
||||
self.bytes_a,
|
||||
enums.OpaqueDataType.NONE,
|
||||
name='Test Opaque Object')
|
||||
|
||||
self.assertEqual(obj.value, self.bytes_a)
|
||||
self.assertEqual(obj.opaque_type, enums.OpaqueDataType.NONE)
|
||||
self.assertEqual(obj.names, ['Test Opaque Object'])
|
||||
|
||||
def test_get_object_type(self):
|
||||
"""
|
||||
Test that the object type can be retrieved from the OpaqueObject.
|
||||
"""
|
||||
expected = enums.ObjectType.OPAQUE_DATA
|
||||
obj = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
observed = obj.object_type
|
||||
self.assertEqual(expected, observed)
|
||||
|
||||
def test_validate_on_invalid_value(self):
|
||||
"""
|
||||
Test that a TypeError is raised when an invalid value is used to
|
||||
construct a OpaqueObject.
|
||||
"""
|
||||
args = (0, enums.OpaqueDataType.NONE)
|
||||
self.assertRaises(TypeError, objects.OpaqueObject, *args)
|
||||
|
||||
def test_validate_on_invalid_data_type(self):
|
||||
"""
|
||||
Test that a TypeError is raised when an invalid data type is used to
|
||||
construct a OpaqueObject.
|
||||
"""
|
||||
args = (self.bytes_a, 'invalid')
|
||||
self.assertRaises(TypeError, objects.OpaqueObject, *args)
|
||||
|
||||
def test_validate_on_invalid_name(self):
|
||||
"""
|
||||
Test that a TypeError is raised when an invalid name value is used to
|
||||
construct a OpaqueObject.
|
||||
"""
|
||||
args = (self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
kwargs = {'name': 0}
|
||||
self.assertRaises(TypeError, objects.OpaqueObject, *args, **kwargs)
|
||||
|
||||
def test_repr(self):
|
||||
"""
|
||||
Test that repr can be applied to a OpaqueObject.
|
||||
"""
|
||||
obj = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
args = "value={0}, opaque_type={1}".format(
|
||||
binascii.hexlify(self.bytes_a), enums.OpaqueDataType.NONE)
|
||||
expected = "OpaqueObject({0})".format(args)
|
||||
observed = repr(obj)
|
||||
self.assertEqual(expected, observed)
|
||||
|
||||
def test_str(self):
|
||||
"""
|
||||
Test that str can be applied to a OpaqueObject.
|
||||
"""
|
||||
obj = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
expected = str(binascii.hexlify(self.bytes_a))
|
||||
observed = str(obj)
|
||||
self.assertEqual(expected, observed)
|
||||
|
||||
def test_equal_on_equal(self):
|
||||
"""
|
||||
Test that the equality operator returns True when comparing two
|
||||
OpaqueObject objects with the same data.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
self.assertTrue(a == b)
|
||||
self.assertTrue(b == a)
|
||||
|
||||
def test_equal_on_not_equal_value(self):
|
||||
"""
|
||||
Test that the equality operator returns False when comparing two
|
||||
OpaqueObject objects with different data.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = objects.OpaqueObject(self.bytes_b, enums.OpaqueDataType.NONE)
|
||||
self.assertFalse(a == b)
|
||||
self.assertFalse(b == a)
|
||||
|
||||
def test_equal_on_not_equal_data_type(self):
|
||||
"""
|
||||
Test that the equality operator returns False when comparing two
|
||||
OpaqueObject objects with different data.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b.opaque_type = "invalid"
|
||||
self.assertFalse(a == b)
|
||||
self.assertFalse(b == a)
|
||||
|
||||
def test_equal_on_type_mismatch(self):
|
||||
"""
|
||||
Test that the equality operator returns False when comparing a
|
||||
OpaqueObject object to a non-OpaqueObject object.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = "invalid"
|
||||
self.assertFalse(a == b)
|
||||
self.assertFalse(b == a)
|
||||
|
||||
def test_not_equal_on_equal(self):
|
||||
"""
|
||||
Test that the inequality operator returns False when comparing
|
||||
two OpaqueObject objects with the same internal data.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
self.assertFalse(a != b)
|
||||
self.assertFalse(b != a)
|
||||
|
||||
def test_not_equal_on_not_equal_value(self):
|
||||
"""
|
||||
Test that the equality operator returns True when comparing two
|
||||
OpaqueObject objects with different data.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = objects.OpaqueObject(self.bytes_b, enums.OpaqueDataType.NONE)
|
||||
self.assertTrue(a != b)
|
||||
self.assertTrue(b != a)
|
||||
|
||||
def test_not_equal_on_not_equal_data_type(self):
|
||||
"""
|
||||
Test that the equality operator returns True when comparing two
|
||||
OpaqueObject objects with different data.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b.opaque_type = "invalid"
|
||||
self.assertTrue(a != b)
|
||||
self.assertTrue(b != a)
|
||||
|
||||
def test_not_equal_on_type_mismatch(self):
|
||||
"""
|
||||
Test that the equality operator returns True when comparing a
|
||||
OpaqueObject object to a non-OpaqueObject object.
|
||||
"""
|
||||
a = objects.OpaqueObject(self.bytes_a, enums.OpaqueDataType.NONE)
|
||||
b = "invalid"
|
||||
self.assertTrue(a != b)
|
||||
self.assertTrue(b != a)
|
|
@ -186,6 +186,8 @@ class TestObjectFactory(testtools.TestCase):
|
|||
b'\x11\xEB\xB2\x5A\x7F\x86')
|
||||
self.secret_bytes = (
|
||||
b'\x53\x65\x63\x72\x65\x74\x50\x61\x73\x73\x77\x6F\x72\x64')
|
||||
self.opaque_bytes = (
|
||||
b'\x53\x65\x63\x72\x65\x74\x50\x61\x73\x73\x77\x6F\x72\x64')
|
||||
|
||||
def tearDown(self):
|
||||
super(TestObjectFactory, self).tearDown()
|
||||
|
@ -395,6 +397,39 @@ class TestObjectFactory(testtools.TestCase):
|
|||
self.assertEqual(enums.SecretDataType.PASSWORD, pie_key.data_type)
|
||||
self.assertEqual(self.secret_bytes, pie_key.value)
|
||||
|
||||
def test_convert_opaque_object_pie_to_core(self):
|
||||
"""
|
||||
Test that a Pie opaque object can be converted into a core opaque
|
||||
object.
|
||||
"""
|
||||
pie_obj = pobjects.OpaqueObject(
|
||||
self.opaque_bytes, enums.OpaqueDataType.NONE)
|
||||
core_obj = self.factory.convert(pie_obj)
|
||||
|
||||
self.assertIsInstance(core_obj, secrets.OpaqueObject)
|
||||
|
||||
opaque_type = core_obj.opaque_data_type.enum
|
||||
self.assertEqual(enums.OpaqueDataType.NONE, opaque_type)
|
||||
|
||||
value = core_obj.opaque_data_value.value
|
||||
self.assertEqual(self.opaque_bytes, value)
|
||||
|
||||
def test_convert_opaque_object_core_to_pie(self):
|
||||
"""
|
||||
Test that a core opaque object can be converted into a Pie opaque
|
||||
object.
|
||||
"""
|
||||
opaque_data_type = secrets.OpaqueObject.OpaqueDataType(
|
||||
enums.OpaqueDataType.NONE)
|
||||
opaque_data_value = secrets.OpaqueObject.OpaqueDataValue(
|
||||
self.opaque_bytes)
|
||||
core_obj = secrets.OpaqueObject(opaque_data_type, opaque_data_value)
|
||||
pie_obj = self.factory.convert(core_obj)
|
||||
|
||||
self.assertIsInstance(pie_obj, pobjects.OpaqueObject)
|
||||
self.assertEqual(enums.OpaqueDataType.NONE, pie_obj.opaque_type)
|
||||
self.assertEqual(self.opaque_bytes, pie_obj.value)
|
||||
|
||||
def test_build_pie_symmetric_key(self):
|
||||
"""
|
||||
Test that a core SymmetricKey object can be converted into a Pie
|
||||
|
|
Loading…
Reference in New Issue