mirror of https://github.com/OpenKMIP/PyKMIP.git
Merge pull request #269 from vbnmmnbv/revoke_pie
Add Revoke operation support for pie client
This commit is contained in:
commit
2891476568
|
@ -110,6 +110,25 @@ class KmipClient:
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def revoke(self, revocation_reason, uid, revocation_message,
|
||||||
|
compromise_occurrence_date):
|
||||||
|
"""
|
||||||
|
Revoke a managed object stored by a KMIP appliance.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
revocation_reason (RevocationReasonCode): An enumeration indicating
|
||||||
|
the revocation reason.
|
||||||
|
uid (string): The unique ID of the managed object to revoke.
|
||||||
|
Optional, defaults to None.
|
||||||
|
revocation_message (string): A message regarding the revocation.
|
||||||
|
Optional, defaults to None.
|
||||||
|
compromise_occurrence_date (int): A integer which will be converted
|
||||||
|
to the Datetime when the managed object was firstly believed to
|
||||||
|
be compromised. Optional, defaults to None.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def destroy(self, uid):
|
def destroy(self, uid):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -17,6 +17,7 @@ import logging
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from kmip.core import enums
|
from kmip.core import enums
|
||||||
|
from kmip.core import primitives
|
||||||
from kmip.core import objects as cobjects
|
from kmip.core import objects as cobjects
|
||||||
|
|
||||||
from kmip.core.factories import attributes
|
from kmip.core.factories import attributes
|
||||||
|
@ -513,6 +514,7 @@ class ProxyKmipClient(api.KmipClient):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
uid (string): The unique ID of the managed object to activate.
|
uid (string): The unique ID of the managed object to activate.
|
||||||
|
Optional, defaults to None.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
|
@ -542,6 +544,66 @@ class ProxyKmipClient(api.KmipClient):
|
||||||
message = result.result_message.value
|
message = result.result_message.value
|
||||||
raise exceptions.KmipOperationFailure(status, reason, message)
|
raise exceptions.KmipOperationFailure(status, reason, message)
|
||||||
|
|
||||||
|
def revoke(self, revocation_reason, uid=None, revocation_message=None,
|
||||||
|
compromise_occurrence_date=None):
|
||||||
|
"""
|
||||||
|
Revoke a managed object stored by a KMIP appliance.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
revocation_reason (RevocationReasonCode): An enumeration indicating
|
||||||
|
the revocation reason.
|
||||||
|
uid (string): The unique ID of the managed object to revoke.
|
||||||
|
Optional, defaults to None.
|
||||||
|
revocation_message (string): A message regarding the revocation.
|
||||||
|
Optional, defaults to None.
|
||||||
|
compromise_occurrence_date (int): An integer, the number of seconds
|
||||||
|
since the epoch, which will be converted to the Datetime when
|
||||||
|
the managed object was firstly believed to be compromised.
|
||||||
|
Optional, defaults to None.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ClientConnectionNotOpen: if the client connection is unusable
|
||||||
|
KmipOperationFailure: if the operation result is a failure
|
||||||
|
TypeError: if the input argument is invalid
|
||||||
|
"""
|
||||||
|
# Check input
|
||||||
|
if not isinstance(revocation_reason, enums.RevocationReasonCode):
|
||||||
|
raise TypeError(
|
||||||
|
"revocation_reason must be a RevocationReasonCode enumeration")
|
||||||
|
if uid is not None:
|
||||||
|
if not isinstance(uid, six.string_types):
|
||||||
|
raise TypeError("uid must be a string")
|
||||||
|
if revocation_message is not None:
|
||||||
|
if not isinstance(revocation_message, six.string_types):
|
||||||
|
raise TypeError("revocation_message must be a string")
|
||||||
|
if compromise_occurrence_date is not None:
|
||||||
|
if not isinstance(compromise_occurrence_date, six.integer_types):
|
||||||
|
raise TypeError(
|
||||||
|
"compromise_occurrence_date must be an integer")
|
||||||
|
|
||||||
|
compromise_occurrence_date = primitives.DateTime(
|
||||||
|
compromise_occurrence_date,
|
||||||
|
enums.Tags.COMPROMISE_OCCURRENCE_DATE)
|
||||||
|
|
||||||
|
# Verify that operations can be given at this time
|
||||||
|
if not self._is_open:
|
||||||
|
raise exceptions.ClientConnectionNotOpen()
|
||||||
|
|
||||||
|
# revoke the managed object and handle the results
|
||||||
|
result = self.proxy.revoke(revocation_reason, uid, revocation_message,
|
||||||
|
compromise_occurrence_date)
|
||||||
|
|
||||||
|
status = result.result_status.value
|
||||||
|
if status == enums.ResultStatus.SUCCESS:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
reason = result.result_reason.value
|
||||||
|
message = result.result_message.value
|
||||||
|
raise exceptions.KmipOperationFailure(status, reason, message)
|
||||||
|
|
||||||
def destroy(self, uid=None):
|
def destroy(self, uid=None):
|
||||||
"""
|
"""
|
||||||
Destroy a managed object stored by a KMIP appliance.
|
Destroy a managed object stored by a KMIP appliance.
|
||||||
|
|
|
@ -351,10 +351,13 @@ class KMIPProxy(KMIP):
|
||||||
results = self._process_batch_items(response)
|
results = self._process_batch_items(response)
|
||||||
return results[0]
|
return results[0]
|
||||||
|
|
||||||
def revoke(self, uuid, reason, message=None, credential=None):
|
def revoke(self, revocation_reason, uuid=None, revocation_message=None,
|
||||||
return self._revoke(unique_identifier=uuid,
|
compromise_occurrence_date=None, credential=None):
|
||||||
revocation_code=reason,
|
return self._revoke(
|
||||||
revocation_message=message,
|
unique_identifier=uuid,
|
||||||
|
revocation_reason=revocation_reason,
|
||||||
|
revocation_message=revocation_message,
|
||||||
|
compromise_occurrence_date=compromise_occurrence_date,
|
||||||
credential=credential)
|
credential=credential)
|
||||||
|
|
||||||
def destroy(self, uuid=None, credential=None):
|
def destroy(self, uuid=None, credential=None):
|
||||||
|
@ -805,11 +808,12 @@ class KMIPProxy(KMIP):
|
||||||
payload_unique_identifier)
|
payload_unique_identifier)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _revoke(self, unique_identifier=None, revocation_code=None,
|
def _revoke(self, unique_identifier=None, revocation_reason=None,
|
||||||
revocation_message=None, credential=None):
|
revocation_message=None, compromise_occurrence_date=None,
|
||||||
|
credential=None):
|
||||||
operation = Operation(OperationEnum.REVOKE)
|
operation = Operation(OperationEnum.REVOKE)
|
||||||
|
|
||||||
reason = objects.RevocationReason(code=revocation_code,
|
reason = objects.RevocationReason(code=revocation_reason,
|
||||||
message=revocation_message)
|
message=revocation_message)
|
||||||
uuid = None
|
uuid = None
|
||||||
if unique_identifier is not None:
|
if unique_identifier is not None:
|
||||||
|
@ -818,7 +822,7 @@ class KMIPProxy(KMIP):
|
||||||
payload = revoke.RevokeRequestPayload(
|
payload = revoke.RevokeRequestPayload(
|
||||||
unique_identifier=uuid,
|
unique_identifier=uuid,
|
||||||
revocation_reason=reason,
|
revocation_reason=reason,
|
||||||
compromise_date=None) # TODO(tim-kelsey): sort out date handling
|
compromise_date=compromise_occurrence_date)
|
||||||
|
|
||||||
batch_item = messages.RequestBatchItem(operation=operation,
|
batch_item = messages.RequestBatchItem(operation=operation,
|
||||||
request_payload=payload)
|
request_payload=payload)
|
||||||
|
|
|
@ -50,6 +50,12 @@ class DummyKmipClient(api.KmipClient):
|
||||||
def activate(self, uid):
|
def activate(self, uid):
|
||||||
super(DummyKmipClient, self).activate(uid)
|
super(DummyKmipClient, self).activate(uid)
|
||||||
|
|
||||||
|
def revoke(self, revocation_reason, uid, revocation_message,
|
||||||
|
compromise_occurrence_date):
|
||||||
|
super(DummyKmipClient, self).revoke(
|
||||||
|
revocation_reason, uid, revocation_message,
|
||||||
|
compromise_occurrence_date)
|
||||||
|
|
||||||
def destroy(self, uid):
|
def destroy(self, uid):
|
||||||
super(DummyKmipClient, self).destroy(uid)
|
super(DummyKmipClient, self).destroy(uid)
|
||||||
|
|
||||||
|
@ -127,6 +133,13 @@ class TestKmipClient(testtools.TestCase):
|
||||||
dummy = DummyKmipClient()
|
dummy = DummyKmipClient()
|
||||||
dummy.activate('uid')
|
dummy.activate('uid')
|
||||||
|
|
||||||
|
def test_revoke(self):
|
||||||
|
"""
|
||||||
|
Test that the revoke method can be called without error.
|
||||||
|
"""
|
||||||
|
dummy = DummyKmipClient()
|
||||||
|
dummy.revoke('reason', 'uid', 'message', 'date')
|
||||||
|
|
||||||
def test_destroy(self):
|
def test_destroy(self):
|
||||||
"""
|
"""
|
||||||
Test that the destroy method can be called without error.
|
Test that the destroy method can be called without error.
|
||||||
|
|
|
@ -24,6 +24,7 @@ from kmip.core import objects as obj
|
||||||
|
|
||||||
from kmip.core.factories import attributes
|
from kmip.core.factories import attributes
|
||||||
from kmip.core.messages import contents
|
from kmip.core.messages import contents
|
||||||
|
from kmip.core.primitives import DateTime
|
||||||
|
|
||||||
from kmip.services.kmip_client import KMIPProxy
|
from kmip.services.kmip_client import KMIPProxy
|
||||||
from kmip.services import results
|
from kmip.services import results
|
||||||
|
@ -949,6 +950,135 @@ class TestProxyKmipClient(testtools.TestCase):
|
||||||
self.assertRaisesRegexp(
|
self.assertRaisesRegexp(
|
||||||
KmipOperationFailure, error_msg, client.activate, *args)
|
KmipOperationFailure, error_msg, client.activate, *args)
|
||||||
|
|
||||||
|
@mock.patch('kmip.pie.client.KMIPProxy',
|
||||||
|
mock.MagicMock(spec_set=KMIPProxy))
|
||||||
|
def test_revoke(self):
|
||||||
|
"""
|
||||||
|
Test that the client can revoke a secret.
|
||||||
|
"""
|
||||||
|
revocation_reason = enums.RevocationReasonCode.KEY_COMPROMISE
|
||||||
|
uuid = 'aaaaaaaa-1111-2222-3333-ffffffffffff'
|
||||||
|
revocation_message = 'Key compromised!'
|
||||||
|
compromise_occurrence_date = 1
|
||||||
|
|
||||||
|
status = enums.ResultStatus.SUCCESS
|
||||||
|
result = results.OperationResult(contents.ResultStatus(status))
|
||||||
|
|
||||||
|
with ProxyKmipClient() as client:
|
||||||
|
client.proxy.revoke.return_value = result
|
||||||
|
result = client.revoke(
|
||||||
|
revocation_reason, uuid, revocation_message,
|
||||||
|
compromise_occurrence_date)
|
||||||
|
client.proxy.revoke.assert_called_with(
|
||||||
|
revocation_reason, uuid, revocation_message,
|
||||||
|
DateTime(compromise_occurrence_date,
|
||||||
|
enums.Tags.COMPROMISE_OCCURRENCE_DATE))
|
||||||
|
self.assertEqual(None, result)
|
||||||
|
|
||||||
|
@mock.patch('kmip.pie.client.KMIPProxy',
|
||||||
|
mock.MagicMock(spec_set=KMIPProxy))
|
||||||
|
def test_revoke_on_invalid_inputs(self):
|
||||||
|
"""
|
||||||
|
Test that a TypeError exception is raised when trying to revoke a
|
||||||
|
secret with invalid inputs.
|
||||||
|
"""
|
||||||
|
revocation_reason = enums.RevocationReasonCode.KEY_COMPROMISE
|
||||||
|
revocation_reason_invalid = "key compromise"
|
||||||
|
|
||||||
|
uuid = 'aaaaaaaa-1111-2222-3333-ffffffffffff'
|
||||||
|
uuid_invalid = 123
|
||||||
|
|
||||||
|
revocation_message = 'Key compromised!'
|
||||||
|
revocation_message_invalid = 123
|
||||||
|
|
||||||
|
compromise_occurrence_date = 1
|
||||||
|
compromise_occurrence_date_invalid = '1'
|
||||||
|
|
||||||
|
args = [revocation_reason_invalid, uuid, revocation_message,
|
||||||
|
compromise_occurrence_date]
|
||||||
|
with ProxyKmipClient() as client:
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
TypeError,
|
||||||
|
"revocation_reason must be a RevocationReasonCode enumeration",
|
||||||
|
client.revoke,
|
||||||
|
*args)
|
||||||
|
|
||||||
|
args = [revocation_reason, uuid_invalid, revocation_message,
|
||||||
|
compromise_occurrence_date]
|
||||||
|
with ProxyKmipClient() as client:
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
TypeError,
|
||||||
|
"uid must be a string",
|
||||||
|
client.revoke,
|
||||||
|
*args)
|
||||||
|
|
||||||
|
args = [revocation_reason, uuid, revocation_message_invalid,
|
||||||
|
compromise_occurrence_date]
|
||||||
|
with ProxyKmipClient() as client:
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
TypeError,
|
||||||
|
"revocation_message must be a string",
|
||||||
|
client.revoke,
|
||||||
|
*args)
|
||||||
|
|
||||||
|
args = [revocation_reason, uuid, revocation_message,
|
||||||
|
compromise_occurrence_date_invalid]
|
||||||
|
with ProxyKmipClient() as client:
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
TypeError,
|
||||||
|
"compromise_occurrence_date must be an integer",
|
||||||
|
client.revoke,
|
||||||
|
*args)
|
||||||
|
|
||||||
|
@mock.patch('kmip.pie.client.KMIPProxy',
|
||||||
|
mock.MagicMock(spec_set=KMIPProxy))
|
||||||
|
def test_revoke_on_closed(self):
|
||||||
|
"""
|
||||||
|
Test that a ClientConnectionNotOpen exception is raised when trying
|
||||||
|
to revoke a secret on an unopened client connection.
|
||||||
|
"""
|
||||||
|
client = ProxyKmipClient()
|
||||||
|
revocation_reason = enums.RevocationReasonCode.KEY_COMPROMISE
|
||||||
|
uuid = 'aaaaaaaa-1111-2222-3333-ffffffffffff'
|
||||||
|
revocation_message = 'Key compromised!'
|
||||||
|
compromise_occurrence_date = 1
|
||||||
|
args = [revocation_reason, uuid, revocation_message,
|
||||||
|
compromise_occurrence_date]
|
||||||
|
self.assertRaises(
|
||||||
|
ClientConnectionNotOpen, client.revoke, *args)
|
||||||
|
|
||||||
|
@mock.patch('kmip.pie.client.KMIPProxy',
|
||||||
|
mock.MagicMock(spec_set=KMIPProxy))
|
||||||
|
def test_revoke_on_operation_failure(self):
|
||||||
|
"""
|
||||||
|
Test that a KmipOperationFailure exception is raised when the
|
||||||
|
backend fails to revoke a secret.
|
||||||
|
"""
|
||||||
|
status = enums.ResultStatus.OPERATION_FAILED
|
||||||
|
reason = enums.ResultReason.GENERAL_FAILURE
|
||||||
|
revocation_message = "Test failure message"
|
||||||
|
|
||||||
|
result = results.OperationResult(
|
||||||
|
contents.ResultStatus(status),
|
||||||
|
contents.ResultReason(reason),
|
||||||
|
contents.ResultMessage(revocation_message))
|
||||||
|
error_msg = str(KmipOperationFailure(status, reason,
|
||||||
|
revocation_message))
|
||||||
|
|
||||||
|
client = ProxyKmipClient()
|
||||||
|
client.open()
|
||||||
|
client.proxy.revoke.return_value = result
|
||||||
|
|
||||||
|
revocation_reason = enums.RevocationReasonCode.KEY_COMPROMISE
|
||||||
|
uuid = 'aaaaaaaa-1111-2222-3333-ffffffffffff'
|
||||||
|
revocation_message = 'Key compromised!'
|
||||||
|
compromise_occurrence_date = 1
|
||||||
|
args = [revocation_reason, uuid, revocation_message,
|
||||||
|
compromise_occurrence_date]
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
KmipOperationFailure, error_msg, client.revoke, *args)
|
||||||
|
|
||||||
@mock.patch('kmip.pie.client.KMIPProxy',
|
@mock.patch('kmip.pie.client.KMIPProxy',
|
||||||
mock.MagicMock(spec_set=KMIPProxy))
|
mock.MagicMock(spec_set=KMIPProxy))
|
||||||
def test_destroy(self):
|
def test_destroy(self):
|
||||||
|
|
Loading…
Reference in New Issue