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:
Peter Hamilton 2015-07-30 08:25:06 -04:00
parent 13dfa14416
commit 93610719a5
4 changed files with 344 additions and 3 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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